performance-optimization について
ゲーム開発者向けの、エンジン横断型のパフォーマンス最適化スキルです。プロファイルで原因を特定し、修正後に再測定する手順と、プーリング、バッチ処理、アセット予算を扱います。
主な機能
- 01計測によるボトルネックの特定
- 02CPUとGPUの負荷の切り分け
- 03オブジェクトプーリングとバッチ処理
- 04フレームごとのメモリ割り当て削減
- 05フレーム時間とアセット予算の設定
活用シーン
- 01低フレームレートやカクつきの調査
- 02CPUとGPUのどちらを最適化するか判断
- 03頻繁なオブジェクト生成の負荷軽減
- 04性能とアセットのチェック体制づくり
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ gamedev-skills/ awesome-gamedev-agent-skills --skill performance-optimizationインストール後、Claude Code で/performance-optimizationを入力して読み込まれたか確認します。
同梱ファイルreferences/profiling-and-budgets.md
詳細
パフォーマンス最適化
パフォーマンス改善は計測の規律であり、裏技の寄せ集めではありません。手順は常に同じです。プロファイリング → 1つのボトルネックを特定 → そこを修正 → 再計測。このスキルでは、このサイクルと効果の大きい修正(プーリング、バッチ処理、アロケーション制御、アセットの予算設定)を解説し、各エンジンのプロファイラーを紹介します。シミュレーションのコストについては physics-tuning と併用してください。
使用する場面
- フレームレートが低い、または不安定な場合、ゲームがカクつく場合、あるいは目標(デスクトップで 60 FPS、モバイルで 30/60 FPS)を達成する必要があるのに、現状では達成できていない場合に使用します。
- 何を最適化するか決める場合に使用します。コードを変更する前にプロファイリングし、フレーム予算を確認して、CPU と GPU のどちらがボトルネックかを特定します。
- 具体的な修正を適用する場合に使用します。オブジェクトプーリング、ドローコール/バッチ処理の削減、フレームごとのアロケーションと GC のスパイクの除去、アセット予算の設定が対象です。
使用しない場面: 物理演算のジッター/トンネリング/タイムステップについては、physics-tuning を使用してください。エンジン固有の具体的なプロファイラー UI やレンダリング設定については、そのエンジンのスキルを使用してください(ビルド設定の一部は godot-export が扱い、残りは各エンジンコアが扱います)。このスキルでは、エンジンを問わない手法と共通の修正を扱います。
鉄則:まず計測し、決して推測しない
プロファイリングせずに適用したパフォーマンス「修正」の多くは、誤った対象に手を加え、効果がないまま複雑さを増やします。計測していないコードを最適化してはいけません。 プロファイラーを開き、代表的なハードウェア上で代表的なシーンを使って、最も大きなコストを1つ特定し、そこを修正してください。先に進む前に再計測して、修正が効果をもたらしたことを確認します。重要な場合は、リリース/最適化ビルドをプロファイリングしてください。エディターやデバッグビルドの結果はあてになりません(エディターのオーバーヘッドがあり、コンパイラー最適化も適用されません)。
基本的なワークフロー
- 目標を定め、再現する。 目標(例:60 FPS = 16.67 ms/frame)を明確にし、繰り返し実行できる最悪ケースのシーンを見つけます。「時々遅い」問題は修正できませんが、再現可能なスパイクなら修正できます。
- コードに手を加える前にプロファイリングする。 エンジンのプロファイラーを実行してフレームを確認します。フレーム全体の時間と、CPU(ゲームロジック、物理演算、スクリプト)と GPU(レンダリング)の内訳を確認します。
- ボトルネックが CPU と GPU のどちらかを特定する。 GPU の時間が CPU より大幅に長い場合は、ドローコール/オーバードロー/シェーダー/解像度に対処します。CPU の時間が支配的な場合は、スクリプト/物理演算/アロケーションに対処します。誤った側を修正しても効果はありません。
- 最も大きなコストを1つ修正する。 ホットな行をマイクロ最適化するよりも、アルゴリズム面での改善(処理量を減らす、キャッシュする、空間分割する、実行頻度を下げる)を優先します。該当する共通の修正(プーリング、バッチ処理、アロケーションの除去)を適用します。
- 同じシーン/ハードウェアで再計測する。 数値が改善したことを確認します。直感ではなく、データに基づいて維持するか元に戻すかを判断します。
- 予算を設定して再発を防ぐ。 サブシステムごとのフレームあたり ms 予算に加え、アセット予算(テクスチャサイズ、三角形数、ドローコールの上限)を設定し、検証にパフォーマンスチェックを追加します。
- 計測した数値を報告する。 変更前後のフレーム時間、特定したボトルネック、修正内容を明記します。「速くなるはずです」ではいけません。エディター内でしか計測できなかった場合は、その旨を伝えます。
パターン
1. フレーム予算の計算(「遅く感じる」を数値にする)
target FPS → frame budget: 60 FPS = 16.67 ms | 30 FPS = 33.3 ms | 120 FPS = 8.33 ms
The WHOLE frame (CPU sim + render submit + GPU) must fit the budget; the GPU runs in parallel,
so the slower of CPU-frame and GPU-frame sets your FPS. Allocate sub-budgets, e.g. @60 FPS:
gameplay/scripts ~5 ms · physics ~3 ms · rendering(CPU submit) ~4 ms · UI/other ~2 ms · slack.
If one subsystem blows its slice, that's your target — not whatever you assumed.
2. エンジンのプロファイラーで計測する(修正の前に必ず実施)
Godot 4.7 : Debugger ▸ Profiler (script/physics time) and Monitors tab (FPS, draw calls, memory).
In code: Performance.get_monitor(Performance.TIME_PROCESS) and
Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME).
Unity 6.3 LTS : Profiler window (CPU/GPU/Memory/Rendering modules) + Frame Debugger for draw calls.
In code: a ProfilerRecorder tracking "CPU Main Thread Frame Time" for a HUD/log.
Unreal 5 : `stat unit` (Frame/Game/Draw/GPU ms), `stat fps`, `stat scenerendering` (draw calls);
Unreal Insights for deep traces.
# Read the split: is the Draw/GPU line the biggest, or the Game/CPU line? That decides the fix.
3. オブジェクトプーリング(負荷の高いループでの確保/解放をやめる)
# Bullets, particles, enemies, damage numbers: reuse a fixed set instead of instantiate()/free()
# every frame — that thrashes memory and (in C#) feeds the GC.
var _pool: Array[Node] = []
func acquire() -> Node:
var n: Node = _pool.pop_back() if not _pool.is_empty() else bullet_scene.instantiate()
n.set_process(true); n.visible = true
return n
func release(n: Node) -> void:
n.set_process(false); n.visible = false # disable + hide; DON'T free
_pool.append(n) # back to the pool for reuse
# RIGHT: pre-warm the pool at load; reuse. WRONG: instantiate()/queue_free() per shot.
4. ドローコールを削減する(GPU 側で最も一般的な改善策)
Each unique material/texture/state change is roughly a draw call; thousands of them stall the GPU.
- Atlas textures and share materials so sprites/meshes batch into one call.
- Identical meshes → GPU instancing (Unity), MultiMesh / MultiMeshInstance (Godot), Instanced
Static Mesh (Unreal).
- Static geometry → static batching / baking; mark non-moving objects static.
- Reduce overdraw: limit large overlapping transparent/particle layers (they re-shade pixels).
- Fewer real-time lights/shadows; bake lighting where it doesn't move.
Measure draw calls before and after — the count should drop, and so should GPU frame time.
5. フレームごとのアロケーションをなくす(GC のスパイクはカクつきの原因)
// Unity 6.3 LTS (C#). Allocating every frame fills the managed heap; the GC then stalls a frame.
// WRONG (allocates each call): foreach (var e in FindObjectsOfType<Enemy>()) ... // + LINQ, new[]
// RIGHT: cache references once, reuse buffers, avoid LINQ/boxing in Update.
void Update() {
_hits = Physics.RaycastNonAlloc(ray, _hitBuffer); // reuse a preallocated array
for (int i = 0; i < _hits; i++) { /* ... */ } // no per-frame allocation
}
// Godot/GDScript: avoid building new arrays/dictionaries every frame in _process; reuse them.
落とし穴
- プロファイリングせずに最適化する。 直感で原因だと思う箇所は、たいてい間違っています。毎回、まず測定してください。
- エディターやデバッグビルドをプロファイリングする。 エディターのオーバーヘッドや最適化されていないコードは、誤った判断を招きます。実際の数値を得るには、対象ハードウェアでリリースビルドをプロファイリングしてください。
- 間違った側を修正する。 GPU がボトルネックなのに CPU コードをマイクロ最適化したり、その逆をしたりしても、何も変わりません。まず CPU と GPU の負荷の内訳を確認してください。
- アルゴリズムよりマイクロ最適化を優先する。 実際のコストが O(n²) のループや毎フレームのシーン全体へのクエリにあるのに、関数の処理を少し削っても効果はありません。磨きをかけるのではなく、処理量を減らしてください。
- 負荷の高いループ内でインスタンスを生成・解放する。 毎フレーム、弾やパーティクルを生成・破棄すると、メモリの断片化や GC の急増につながります。プールを使ってください。
Update内での毎フレームの割り当て/LINQ/ボックス化(C#)は GC を増やし、定期的なカクつきを引き起こします。キャッシュして再利用してください。- 固有のマテリアルやバッチ化されていないスプライト/メッシュによる描画コールの急増。 アトラスを使い、マテリアルを共有し、インスタンス化し、バッチ化してください。
- オーバードロー。 重なった透明オブジェクト/パーティクル/全画面エフェクトによって、ピクセルが何度も再シェーディングされます。
- 予算を設定しない。 サブシステムごとの処理時間(ms)やアセットの上限がないと、パフォーマンスは気づかないうちに低下します。ビルド/CI のチェックで上限を適用してください。
- 早すぎる最適化。 試作品が面白くなる前や測定する前に、パフォーマンスのために設計を無理に曲げないでください。
参考資料
- エンジンごとのプロファイラーの使い方、CPU と GPU の切り分けフローチャート、完全なプーリングマネージャー、エンジンごとのバッチ化/インスタンス化のルール、割り当て/GC に関するガイダンス、LOD/カリング、アセット予算(テクスチャサイズ、三角形数、オーディオ、モバイル端末の熱対策)については、
references/profiling-and-budgets.mdをお読みください。
関連スキル
physics-tuning— シミュレーションのコスト、固定ステップの予算、スリープ状態の剛体、ブロードフェーズのレイヤー。godot-export— 測定したパフォーマンスに影響するリリース/ビルド設定。procedural-gen、game-ai— 予算を設定し、後回しにすべき、よくある CPU のホットスポット(生成、経路探索)。roguelike、tower-defense、survival-crafting— エンティティ数が多く、プーリング/予算管理が必要なジャンル。