「オブジェクトの数を増やしただけなのに、急にゲームがカクカクし始めた」「Profilerを見てもどこが重いのかよくわからない」——Unityでゲームを作っていると、こんな壁にぶつかることがありますよね。
実はこの処理落ち、Updateの中身が重いわけではなく、ある「回数」が関係しているケースが多いんです。この記事では、その原因の正体と、Update呼び出しを間引いて軽量化するための具体的な方法を順番に紹介していきます。
今のプロジェクトでその対策が必要かどうかの見極め方から、実際の実装方法、そして改善できたかを確認する方法まで、迷わず行動できるようにまとめました。
Unityの処理落ちはUpdateの回数が原因
まず結論からお伝えすると、Unityで処理落ちが起きる大きな原因のひとつは、Update内の処理が重いことよりも「Updateが何回呼ばれているか」にあります。
たとえ中身がほとんど空っぽのUpdateでも、これが数千個のオブジェクトそれぞれに存在していると、それだけでフレームレートがガクッと落ちることがあるんです。「え、中身が軽いのに?」と意外に思う方も多いところですね。
この理由は、Unityの仕組みそのものにあります。Unityのエンジン部分はC++というプログラミング言語で作られていて、私たちが書くゲームロジックはC#で書かれています。Updateが1回呼ばれるたびに、このC++とC#の間を行き来する処理が発生していて、これに意外とコストがかかるんです。
つまり、オブジェクトが1個増えるごとに「境界を渡る回数」も1回増えていくイメージです。10個や100個なら気にならなくても、これが1000個、10000個と積み重なると、その行き来のコストだけでCPUの時間をかなり消費してしまいます。
Profilerを開いたときに「BehaviourUpdate」といった項目が目立って重くなっている場合、まさにこのUpdate呼び出しの回数が影響している可能性が高いといえます。

ここまでで「なぜ重くなるのか」の正体がつかめたと思います。次は、自分のプロジェクトで実際に対策が必要なのかどうかを見ていきましょう。
Updateを間引くべきか判断する目安
原因がわかったところで気になるのが、「自分のプロジェクトも対策すべきなのか」ということですよね。すべてのゲームでUpdateの間引きが必須というわけではないので、ここで判断基準を整理しておきましょう。
目安として、以下のような状況に当てはまる場合は、対策を検討する価値があります。
- 敵キャラや弾、アイテムなど、同じ種類のオブジェクトが数百〜数千個同時に存在する
- オブジェクトの数を増やすほどフレームレートが目に見えて落ちていく
- Profilerで「BehaviourUpdate」や似た項目のコストが目立って高い
- スマートフォンなど、処理性能に余裕が少ない端末での動作を想定している
逆に、登場するオブジェクトが数十個程度で、フレームレートも安定しているなら、今すぐ手を加える必要性は高くありません。オブジェクト数がそれほど多くない状態で間引きの仕組みを導入しても、コードが複雑になる割に体感できる効果は小さいことが多いからです。
ただし、Updateの呼び出し回数だけがパフォーマンスを左右する要因ではありません。テクスチャの解像度やメモリの使い方、描画の設定なども関係してくるので、全体的に重さを感じている場合は、まず何が原因になっているのかを広い視点で確認するのもひとつの方法です。そのあたりを網羅的に知りたい方は、こちらの記事も参考になります。
コチラの記事もあわせてチェックしてみてください。

次はいよいよ具体的な対策方法に進んでいきましょう。
Update呼び出しを減らす3つの方法
ここからは、実際にUpdateの呼び出し回数を減らすための具体的な方法を3つ紹介します。それぞれ得意な場面が違うので、自分が作っている処理に近いものから読んでみてください。
なお、ここで扱うのはあくまで「Update」の間引きについてです。物理演算に使うFixedUpdateは役割が異なるので、間引きの対象にはあたりません。両者の違いをきちんと整理したい方は、こちらの記事が参考になります。
コチラの記事もあわせて確認してみてください。
一括アップデートで呼び出しを1回にまとめる
一番効果が大きいのが、この一括アップデートという方法です。考え方はシンプルで、オブジェクトごとにバラバラにUpdateを呼ぶのではなく、管理役のクラスがまとめて1回だけ呼び出し、その中でC#のループを回して全オブジェクトを処理する、という形に変えます。
手順としては、次のような流れになります。
- 各オブジェクトのスクリプトから「void Update()」を削除する
- 更新処理を持たせるための共通ルール(インターフェース)を用意する
- シーンに1つだけ管理役のクラス(マネージャー)を作り、そこにオブジェクトのリストを持たせる
- 各オブジェクトは有効になったタイミングでリストに自分を登録し、無効になったら登録を解除する
- マネージャーのUpdate内で、リストに登録された全オブジェクトの処理をforループでまとめて実行する
この方法を使うと、C++とC#の間を行き来する回数が「オブジェクトの数だけ」から「1フレームに1回」まで減るので、数が多いほど効果を実感しやすくなります。
ただし、注意しておきたい点がひとつあります。それは、リストを処理している最中にオブジェクトが生成されたり削除されたりすると、エラーが起きやすいということです。これを避けるには、追加や削除の依頼をいったん別の場所に溜めておいて、フレームの始まりや終わりのタイミングでまとめてリストに反映する、という形にするのが安全です。
また、特定のオブジェクトを先に更新したい場合は、優先度の情報を持たせてリストを並び替えるという方法もあります。あわせて、SetActiveによる表示・非表示の切り替えにも処理コストがかかるため、1フレームの中で何度も繰り返さないよう気をつけておくと安心です。
この仕組みを自作するのはやや手間がかかるので、既製のアセットを活用するという選択肢もあります。
アップデート管理・オブジェクトプーリング系アセット
✅アセットストアでチェックする
プーリングの考え方についてもっと詳しく知りたい方は、こちらの記事も参考にしてみてください。
イベント駆動で監視処理自体をなくす
2つ目は、そもそも毎フレーム状態を見張るのをやめて、何かが起きた瞬間だけ処理を動かすという考え方です。たとえば「クリックされた」「ダメージを受けた」といったタイミングだけ動けばいい処理なら、この方法がぴったりです。
実装の流れはこんな感じになります。
- 状態が変化する側のクラスで、C#のeventやActionを用意しておく
- 変化が起きた瞬間に、そのeventやActionを呼び出す(Invokeする)
- 処理を実行したい側のクラスは、OnEnableのタイミングでイベントに処理を登録する(+=)
- OnDisableのタイミングで、忘れずに登録を解除する(-=)
この方法のいいところは、無駄な監視処理がなくなってCPU負荷が下がるだけでなく、「何がきっかけでこの処理が動いたのか」がコードを読むだけで分かりやすくなる点です。不具合が起きたときの原因調査もぐっと楽になります。
ひとつだけ気をつけたいのが、OnDisableでの登録解除を忘れてしまうケースです。これを忘れると、オブジェクトが消えたはずなのにイベントの参照だけが残り続けて、メモリリークにつながることがあります。登録した処理は必ずセットで解除する、という意識を持っておくと安心です。
コルーチン・Invokeで間隔実行に切り替える
3つ目は、「毎フレーム監視する」処理を「数秒おきに実行する」処理に置き換える方法です。たとえば、1秒に1回だけ状態をチェックすれば十分な処理であれば、わざわざ毎フレーム動かす必要はありません。
代表的な方法が2つあります。
- コルーチン:戻り値をIEnumeratorにして、処理を止めたい場所で「yield return new WaitForSeconds(秒数)」のように書くことで、指定した間隔での実行や待機ができます。呼び出しにはStartCoroutineを使います。
- Invoke:「Invoke(関数名, 秒数)」で指定時間後に一度だけ処理を呼んだり、「InvokeRepeating()」で一定間隔ごとに繰り返し呼んだりできます。不要になったらCancelInvoke()で止められます。
コルーチンについてもう少し詳しい仕組みや、async/awaitとの違いが気になる方はこちらもどうぞ。
この方法は、一括アップデートほど大がかりな設計変更をしなくても導入しやすいのが魅力です。まずは負荷の高い処理から、この方法で間引けないか試してみるのもおすすめです。

3つの方法を紹介しましたが、実際に手を加えたあとは「本当に効果が出ているのか」を確認したくなりますよね。次は、その確認方法を見ていきましょう。
改善効果をProfilerで確認する方法
間引きの実装が終わったら、次に気になるのは「実際にどれくらい効果が出ているのか」ですよね。感覚だけで判断せず、Profilerを使って数値で確認しておくと安心です。
確認の手順はシンプルです。
- Unityのメニューから Window > Analysis > Profiler を開く
- CPU Usageの項目を選び、実際にゲームを再生する
- Timelineモードで、対策前後の「BehaviourUpdate」などUpdate関連の項目を見比べる
- フレームごとの処理時間(ミリ秒)が下がっているかをチェックする
対策前と対策後で同じシーン・同じ条件で計測して比べると、効果がわかりやすくなります。呼び出し回数がきちんと減っていれば、この項目のコストが目に見えて小さくなっているはずです。
ここで注意しておきたいのが、Profiler上の項目名や表示のされ方は、Unityのバージョンによって多少異なる場合があるという点です。「BehaviourUpdate」という名称で見つからない場合は、近い名前の項目がないか探してみてください。
また、Update呼び出しの回数を減らしても、メモリの使い方(GC Alloc)に問題が残っていると、別の原因でカクつきが起きることもあります。Update関連の数値が改善しているのに体感の重さがあまり変わらない場合は、そちらの可能性も視野に入れてみるとよさそうです。
数値をこまめに確認する習慣をつけたい場合は、FPSやメモリの状態を画面上に常時表示できるアセットを使うのもひとつの手です。標準のProfilerより手軽に、日々の変化を追いやすくなります。
Profiler拡張・FPSモニタリングアセット
✅アセットストアでチェックする

推測だけで「軽くなった気がする」で終わらせず、数値で確認する癖をつけておくと、今後別の最適化を行うときにも役立ちます。
まとめ
Unityの処理落ちは、Updateの中身の重さよりも「呼び出し回数」が原因になっていることが多いとお伝えしてきました。まずはProfilerで現状を確認し、オブジェクト数が多い場面では一括アップデート、状態変化がきっかけになる処理にはイベント駆動、間隔実行でよい処理にはコルーチンやInvokeというように、処理の性質に合わせて手法を選んでみてください。
すべてを一度に完璧にする必要はありません。まずは一番負荷が大きい処理からひとつずつ試して、Profilerで効果を確認しながら進めていくのが、無理なく確実な近道です。
よくある質問(FAQ)
- Qスマートフォン向けゲームでもUpdate間引きは必須ですか?
- A
必須というわけではありませんが、優先度は高めに考えておくとよさそうです。スマートフォンはPCに比べて処理性能に余裕が少ない端末が多く、同じ数のオブジェクトでもPCでは気にならなかった処理落ちが、スマートフォンでは目立って現れることがあります。
登場するオブジェクトの数が少ないシンプルなゲームであれば、無理に対策を急ぐ必要はありません。ただ、敵キャラや弾などが画面に多く出るタイプのゲームをスマートフォン向けに作っている場合は、早い段階でUpdateの呼び出し回数を意識しておくと、あとから重さに悩まされにくくなります。
- QAwakeやStartも同じように呼び出し回数を気にする必要がありますか?
- A
AwakeやStartについては、Updateほど神経質になる必要はありません。UpdateやFixedUpdateは毎フレーム呼び出されるのに対して、AwakeやStartはオブジェクトが生成されたときや有効になったときに一度だけ呼ばれる処理だからです。
そのため、オブジェクトの数が多くても、毎フレーム積み重なっていくUpdateのようなコストにはなりません。ただし、Instantiateで大量のオブジェクトを一度に生成すると、その瞬間にAwakeやStartがまとめて実行されるため、生成のタイミングに一時的な負荷が集中することはあります。気になる場合は、オブジェクトを生成するタイミングを分散させたり、あらかじめ用意しておく仕組みを取り入れたりすると負荷を抑えやすくなります。











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