ゲームがカクつく。オブジェクトを減らしてみたり、Update()の中身をコメントアウトしてみたり、影を切ってみたり——それでも直らない。この「手当たり次第に削ってみる」やり方がうまくいかないのは、犯人を推測で捜しているからです。
パフォーマンス最適化の鉄則は1行です。 「推測するな、計測せよ」。そのための計測ツー ルが、Unityに標準搭載されている Profiler です。
この記事でわかること
- 最適化の進め方——計測→特定→修正→再計測のループ
- Profilerの基本操作(Record・フレーム選択)
- CPU Usageモジュールの読み方——Time ms・Self ms・GC Alloc列で犯人を特定する
- 重い処理の典型パターンと対応する記事
- 実機プロファイリングのやり方(Development Build)
動作確認環境: Unity 6 (6000.x)
鉄則: 推測するな、計測せよ
最適化は、次のループで進めます。

- 計測: Profilerで記録し、スパイク(突出した山)を見つける
- 特定: そのフレームで一番時間を食っている処理を突き止める
- 修正: 一番重い1箇所だけを直す
- 再計測: 効果が出たかを数字で確認する
重要なのは、一度に1箇所しか直さないことです。まとめて直すと、どの修正が効いたのか(あるいは逆効果だったのか)がわからなくなります。また、全体の1%しか占めない処理をいくら速くしても、体感は1%も変わりません。常に「今一番重いもの」から手を付けます。
Profilerの基本操作
- 開く: メニューの「Window > Analysis > Profiler」を選択します(ショートカット:
Ctrl + 7)。 - 記録する: 「Record」ボタンがオンの状態でゲームを 再生すると、グラフがリアルタイムに流れ始めます。
- フレームを選ぶ: グラフ上でカクついた瞬間——スパイク(突出した山)をクリックします。そのフレームの処理内訳がウィンドウ下部に表示されます。
tips グラフを眺めるときは、まず色の凡例に注目してください。スパイクの山が何色でできているか(Scripts=水色ならコード、Rendering=緑なら描画、GarbageCollector=茶色ならGCの掃除。黄色はVSyncの待ちなので、犯人ではありません)で、犯人のジャンルが一目で絞れます。
CPU Usage——犯人捜しの主戦場
カクつき調査で最初に見るのは CPU Usage モジュールです。スパイクしたフレームをクリックしたら、下部のビューを Hierarchy に切り替えます。

そのフレームで実行されたすべての処理が階層リストで表示されます。見るべき列は3つだけです。
| 列 | 意味 | 使い方 |
|---|---|---|
| Self ms | その処理自体にかかった時間 | 展開した先で、これが大きい行が犯人 |
| Time ms | 子の処理を含めた合計時間 | 降順に並べて、大きい行から展開していく |
| GC Alloc | そのフレームで確保したヒープメモリ量 | 毎フレーム0以外ならGCスパイクの火種 |
手順はいつも同じです。 「スパイクをクリック → Hierarchyを開く → Time msの大きい行を展開 → 末端でSelf msの大きい行を疑う」。Self msで並べるだけだと、時間を子の処理に任せている親の行が小さく出て、重い処理の入口を見落とします。自分のスクリプトはスクリプト名.Update()のような名前で表示されるので、階層を展開して具体的なメソッドまで掘り下げます。
tips 自分のコードの特定区間を計測したいときは、
UnityEngine.Profiling.Profiler.BeginSample("EnemyAI")とProfiler.EndSample()で囲むと、Hierarchyに「EnemyAI」という名前付きの行として表示されます。「Updateのどの部分が重いのか」まで絞り込めます。
重い処理の典型パターン
Hierarchyの上位によく現れる「常連」と、その対策記事です。

| Profilerでの見え方 | 犯人 | 対策 |
|---|---|---|
GC.Collectの巨大なスパイク | 毎フレームのヒープアロケーション | GC対策 |
Instantiate / Destroyが頻出 | 弾・敵・エフェクトの大量生成破棄 | オブジェクトプーリング |
自作スクリプトのUpdate()が上位 | ループ内のGetComponent・重い検索・毎フレームの文字列処理 | GetComponentのキャッシュ |
Camera.Renderが重い・RenderingモジュールのBatchesが多い | ドローコール過多 | ドローコールとバッチング |
Physics.ProcessingやPhysics.Simulateが重い | Collider過多・Mesh Collider多用 | 形状の単純化・FixedUpdate設定の見直し |
実践:GCスパイクを特定して退治する
ここまでの手順を、実際によくあるケースで通しでやってみましょう。「数秒に一度、周期的にカクつく」——シューティングでもRPGでも頻発する、GCスパイクの典型症状です。
- 計測: Recordをオンにしてプレイし、カクついた瞬間の赤いスパイクをクリック。
- 特定: Hierarchyを開くと、
GC.Collectが数十msを占有しています。Unity 6 は Incremental GC が既定でオンで、掃除はふだん数フレームに分けて小さく行われますが、ゴミを作る量が多くて追いつかないと、こうした大きな山になります。ただしGC.Collectは「掃除した瞬間」であって真犯人ではありません。GC Alloc列で降順に並べ、大きい行を展開していくと——ScoreUI.Update()が毎フレーム2.3 KB確保していました。中身は"Score: " + scoreの文字列連結です。 - 修正: 毎フレームの文字列生成をやめます。スコアが変わったときだけ
textを更新する(イベント駆動にする)だけで、このアロケーションはゼロになります。 - 再計測: 同じ場面を記録し、GC Allocが
0 Bになったこと、周期的なスパイクが消えたことを数字で確認します。
