1. はじめに
Unityでゲームを作っていると、つい便利だからとUpdate()メソッドに処理を詰め込んでしまうことってありませんか?
実際、私も最初の頃は「とりあえずUpdateに書けば毎フレーム動いてくれるから安心!」と多用していました。
でも、この方法には落とし穴があります。Update()が増えるほど、Unity内部での呼び出し回数が膨大になり、結果的にゲームの動作が重くなったり、フレームレートが安定しなくなる原因になるのです。
つまり「ゲームは作れたけど、動きがカクついて遊びにくい…」という状況になりがちなんですね。
そこでこの記事では、Updateを減らしながらゲームのパフォーマンスを改善する方法をまとめてご紹介します。イベント駆動やコルーチン、Invokeの活用など、初心者でもすぐに試せるテクニックを中心に解説していきます。
また、コードの管理やデバッグを快適にしてくれる便利アセットや学習書籍もあわせて紹介するので、これからUnityを本格的に学びたい方にも役立つ内容になっています。
開発の基礎をしっかり学びたい方にはこちらもおすすめです:
Unity 3Dゲーム開発ではじめるC#プログラミング
2. MonoBehaviourのUpdateが抱える問題
Unityでよく使われるMonoBehaviourクラスには、Start()やUpdate()といった「マジックメソッド」が用意されています。
これらを定義すると、Unityは内部で専用のリストに登録し、毎フレーム自動的に呼び出してくれる仕組みになっています。
一見とても便利ですが、実はここにパフォーマンスの落とし穴が潜んでいます。
なぜなら、Unityのコア部分はC++で作られており、私たちが書くC#コードとやり取りするたびに「呼び出しのオーバーヘッド」が発生するからです。Updateを持つスクリプトが増えるほど、この小さな負担が積み重なり、フレームレート低下の原因となってしまいます。
さらに、Updateの実行順序は保証されていません。
例えば「プレイヤーの移動」と「カメラの追従」をそれぞれのUpdateに書いた場合、フレームによってはカメラが先に動いてしまい、カクついた挙動(フレームジャンプ)が発生することもあります。

つまり「とりあえずUpdateに書けば動く」という発想は、開発の初期こそ楽でも、規模が大きくなるほどパフォーマンスや制御の難しさにつながるのです。
3. イベント駆動による最適化
毎フレームUpdate()で状態を監視する代わりに、イベント駆動を取り入れると処理を効率化できます。
イベント駆動とは「何かが起きたときだけ処理を呼び出す仕組み」のことです。これにより、無駄なチェックを省き、必要なタイミングだけ動作させられるようになります。
用語解説
- 発行(発火):イベントを起こす側の処理。例:
event?.Invoke() - 購読:イベントを受け取る側が処理を登録すること。例:
event += 関数名 - 解除:購読をやめること。例:
event -= 関数名
Unityでは、よくOnEnable()で購読を登録し、OnDisable()で解除する書き方が使われます。これにより、オブジェクトが有効な間だけイベントを受け取れるようになり、安全です。
C#でよく使う型
| 型 | 用途 | 例 |
|---|---|---|
event | 外部から発火できない安全なイベント定義 | public event Action OnClick; |
Action | 戻り値なしの処理 | Action<int> onDamage; |
Func | 戻り値ありの処理 | Func<int, string> converter; |
実装例:クリックで色を変える処理
例えば「クリックされたらUIの色を変える」機能は、Updateでマウス入力を毎フレーム監視するよりも、イベントを使う方が効率的です。
// 入力を発行するクラス
public class ClickBroadcaster : MonoBehaviour, IPointerClickHandler {
public static event Action OnButtonClicked;
public void OnPointerClick(PointerEventData eventData) {
OnButtonClicked?.Invoke();
}
}
// 色を変えるクラス
public class ColorChanger : MonoBehaviour {
private void OnEnable() {
ClickBroadcaster.OnButtonClicked += ChangeColor;
}
private void OnDisable() {
ClickBroadcaster.OnButtonClicked -= ChangeColor;
}
private void ChangeColor() {
GetComponent<Image>().color = Color.red;
}
}
このようにイベント駆動を活用すると、Updateで毎フレームInput.GetMouseButtonDown()を呼ぶ必要がなくなり、CPU負荷を下げられます。

イベントやデリゲートを使うとコードが複雑になりがちですが、Odin Inspectorのようなインスペクタ拡張ツールを使えば、エディタ上で状態を可視化でき、開発効率がぐんと上がります。
4. Updateを減らしてパフォーマンスを向上させる5つの方法
ここからは、実際にUpdate()の使用を最小限に抑えてゲームを軽くする具体的な方法を5つ紹介します。どれも実践的で、すぐに自分のプロジェクトに取り入れられるテクニックです。
方法1: FixedUpdate()やLateUpdate()を活用する
- FixedUpdate():物理演算(
Rigidbodyを使った移動など)に最適。一定間隔で実行されるため安定した動きが可能。 - LateUpdate():すべてのUpdate処理が終わった後に呼ばれる。カメラの追従処理などに使うと、オブジェクトの動きを確実に反映できる。
方法2: コルーチン(Coroutine)を活用する
「毎フレーム監視」ではなく「必要な時だけ実行」に切り替えられるのがコルーチンの強みです。
IEnumerator FlashColor() {
GetComponent<Renderer>().material.color = Color.red;
yield return new WaitForSeconds(3f); // 3秒待つ
GetComponent<Renderer>().material.color = Color.blue;
}
上記のように「3秒後に青に変える」といった処理を、Updateを使わずに実現できます。
方法3: イベント駆動を活用する
特定のタイミングでだけ処理を実行する方法です。 例:OnTriggerEnter()でプレイヤーがエリアに入った時だけ敵を動かす、ボタンが押されたときだけUIを更新するなど。
方法4: タイマーとInvoke()を利用する
「時間経過」をUpdateで毎フレームチェックする代わりに、Invoke()やInvokeRepeating()を活用します。
void Start() {
InvokeRepeating("Attack", 0f, 3f); // 3秒ごとにAttackを実行
}
void Attack() {
Debug.Log("攻撃!");
}
不要になったらCancelInvoke()で停止可能です。
方法5: Update自体を使わない設計にする
シングルトンやマネージャークラスを導入することで、Updateをほとんど使わない設計が可能になります。
- 個々のオブジェクトには
Updateを置かず、代わりにManagedUpdate()を用意。 - マネージャークラスが全オブジェクトをリストで管理し、1つの
Updateからまとめて呼び出す。 - 呼び出し回数が減り、実行順序の制御も容易になる。

こうした最適化を行う際には、処理の流れをしっかり把握することも重要です。 Editor Console Proを使えばログ管理が強化され、Updateの呼び出し順や処理の重さをデバッグしやすくなります。
5. コルーチンの基礎と応用
コルーチン(Coroutine)は、Unityにおける「中断できる処理のまとまり」です。
特定のタイミングで処理を止めたり、数秒待ってから再開させたりできるため、Updateを使わずに時間制御や非同期的な動きを表現できます。
基本的な使い方
- 宣言:戻り値を
IEnumeratorにするIEnumerator SampleCoroutine() { ... } - 停止:処理を止めたい箇所で
yield returnを使う - 実行:
StartCoroutine("関数名")で呼び出す
// 例:色を赤にして3秒後に青に戻す
IEnumerator ChangeColor() {
GetComponent<Renderer>().material.color = Color.red;
yield return new WaitForSeconds(3f); // 3秒待つ
GetComponent<Renderer>().material.color = Color.blue;
}
void Start() {
StartCoroutine("ChangeColor");
}
yieldの使い方
yield return null;→ 1フレームだけ停止yield return new WaitForSeconds(2f);→ 2秒待機yield break;→ コルーチンを終了
応用的な使い方
- 途中終了:状況によって処理を中断させたいときは
yield breakを活用 - 複数コルーチン:別のコルーチンを
StartCoroutine()で呼び出して並行処理も可能 - シーケンス処理:アニメーションや演出を「◯秒待ってから順番に実行」するときに便利

例えば「アイテム取得 → 数秒後にエフェクト再生 → さらに数秒後に削除」といった流れを自然に記述できます。
Updateを使わずに時間を扱えるので、処理の見通しも良くなります。
6. Update・LateUpdate・FixedUpdateの比較と活用例
Unityでゲームを動かすうえで欠かせないのがUpdate()ですが、実は似たような仕組みとしてLateUpdate()やFixedUpdate()も存在します。
それぞれの役割を理解して正しく使い分けることで、処理落ちやカクつきを防ぐことができます。
役割の違いまとめ
| 関数名 | 実行タイミング | 主な用途 | 特徴 |
|---|---|---|---|
Update | 毎フレームの先頭 | 入力処理、アニメーション、ゲームロジック全般 | フレームレートに依存するため、秒間の実行回数は環境によって変化 |
LateUpdate | 全てのUpdateが終了した後 | カメラ追従や後処理 | 「オブジェクトの動きが終わったあとに処理する」用途に最適 |
FixedUpdate | 一定間隔(デフォルト0.02秒ごと) | 物理演算(Rigidbodyの移動、AddForceなど) | フレームレートに依存せず、常に一定間隔で実行される |
等速移動の注意点
UpdateやLateUpdateはフレーム間隔が不安定なため、オブジェクトを等速で動かす場合は必ずTime.deltaTimeを掛け算する必要があります。
void Update() {
transform.Translate(Vector3.forward * 5f * Time.deltaTime);
}
カメラ追従での失敗例と解決策
よくある失敗が「プレイヤーの移動」と「カメラの追従」を両方Updateに書いてしまうケースです。
この場合、実行順序が保証されないため、カメラが一瞬遅れて動き「カクつき(フレームジャンプ)」が発生します。
解決策はシンプルで、プレイヤーの移動はUpdateに、カメラの追従はLateUpdateに分けることです。これで常に最新のプレイヤー位置を参照でき、スムーズに追従できます。
// プレイヤーの移動
void Update() {
transform.Translate(Vector3.forward * 5f * Time.deltaTime);
}
// カメラの追従
void LateUpdate() {
transform.position = player.position + offset;
}

このように用途を正しく使い分けることで、Updateの無駄を減らしつつ快適な動きを実現できます。
7. まとめ
今回は、Unityでよく使われるUpdate()を減らしてパフォーマンスを最適化する方法をご紹介しました。
ポイントを振り返ると次の通りです。
Update()の多用は処理落ちやフレームレート低下の原因になる- イベント駆動を使えば「必要なときだけ処理」を実現できる
- コルーチンで時間制御を行うと、Updateが不要になるケースが多い
FixedUpdate()やLateUpdate()を正しく使い分けることで処理が安定する- マネージャークラスでUpdateを一元管理すると大規模プロジェクトでも効率的
こうした工夫を積み重ねることで、無駄のない軽量なゲーム設計が可能になります。
「とりあえずUpdateに書く」から卒業して、イベントやコルーチンをうまく活用していきましょう!
効率的な開発をサポートしてくれるアセットや書籍も活用すると、さらに安心です。
✔ デバッグ効率を上げるなら → Editor Console Pro
✔ インスペクタ拡張でコード管理をラクにするなら → Odin Inspector and Serializer
✔ 学習を基礎から進めたいなら → Unity 3Dゲーム開発ではじめるC#プログラミング
✅ Amazonでチェックする|✅ 楽天でチェックする
あわせて読みたい
Unityの最適化は「Updateを減らす」以外にもさまざまなアプローチがあります。さらに理解を深めたい方は、以下の記事もチェックしてみてくださいね。
- 【Unity】Updateを使わずにくり返し処理を実行する簡単スクリプト
- Unityで最適化をマスター!軽量でスムーズなゲームを作る方法
- Unityでオブジェクトプールを実装する方法と最適化ポイント
- UnityのECSで超高速処理!ゲームのパフォーマンスを飛躍的に向上させる方法
- Unityのコードをリファクタリング!初心者でもできる最適化&整理術
よくある質問(FAQ)
- QUpdateを完全に使わないのは可能ですか?
- A
完全にゼロにするのは現実的ではありません。例えばプレイヤーの入力処理やカメラ制御など、毎フレーム確認が必要な場面は必ずあります。
ただし「全てをUpdateで管理する」のではなく、イベントやコルーチンと組み合わせることで必要最低限のUpdateに抑えるのが理想です。
- Qコルーチンを多用すると逆に重くなりませんか?
- A
コルーチンは内部的に軽量な仕組みで動いているため、通常の範囲であればパフォーマンスに大きな問題はありません。
ただし、数千単位で同時に実行したり、停止処理を忘れて放置すると無駄な処理が残り続けてしまうことがあります。
不要になったらStopCoroutine()やyield breakで終了させましょう。
- Qイベント駆動にするとデバッグが難しくなりませんか?
- A
確かに「どこでイベントが発火しているのか」が分かりづらくなることがあります。
その場合はログを丁寧に出力したり、Editor Console Proのようなデバッグ支援アセットを導入すると効率的に確認できます。
また、購読と解除をOnEnable/OnDisableにまとめると、コードの見通しも良くなります。







※当サイトはアフィリエイト広告を利用しています。リンクを経由して商品を購入された場合、当サイトに報酬が発生することがあります。
※本記事に記載しているAmazon商品情報(価格、在庫状況、割引、配送条件など)は、執筆時点のAmazon.co.jp上の情報に基づいています。
最新の価格・在庫・配送条件などの詳細は、Amazonの商品ページをご確認ください。