背景の小物を並べ、木を植え、敵を増やす——シーンが賑やかになるほどフレームレートが落ちていく。Gameビューの「Stats」を開くと、Batchesの数字が数千に膨れ上がっている。犯人は ドローコール(Draw Call) です。
ドローコールとは、CPUからGPUへの「このメッシュを、このマテリアルで描いて」という描画命令のこと。GPUの描画能力にはまだ余裕があるのに、命令を出すCPU側が先に限界を迎える——これがドローコール過多の典型症状です。
この記事でわかること
- ドローコールがなぜCPUの負荷になるのか(レストランの注文メタファー)
- 現状把握——StatsウィンドウとFrame Debugger
- 削減テクニック4つの使い分け——SRP Batcher・スタティックバッチング・GPUインスタンシング・ダイナミックバッチング
- マテリアルを共有させるテクスチャアトラス
- 実践:賑やかな森ステージのBatchesを実際に減らす
ドローコールとは——注文票のたとえ
CPUとGPUの関係は、ウェイター(CPU)と厨房のシェフ(GPU) に似ています。シェフの調理(描画)は速いのですが、ウェイターは注文票1枚ごとに厨房へ往復し、そのたびに「使う食材(テクスチャ)」「調理法(シェーダー設定)」を伝え直さなければなりません。
- レンダリングステートの設定: どのシェーダー・テクスチャ・ブレンドモードを使うかをGPUに設定する
- 描画命令の発行: 「描画実行」の命令(ドローコール)を出す
問題は、マテリアルが変わるたびにこの「伝え直し」が発生することです。赤い車と青い車はメッシュが同じでも、マテリアルが違えば別々の注文になります。オブジェクト1,000個がそれぞれ別マテリアルなら、毎フレーム1,000回の往復——CPUはこれだけで手一杯になります。

対策の方向はひとつです。 「同じ注文はまとめて1枚の伝票にする」——これが バッチング(Batching) です。
まず現状を数える——StatsとFrame Debugger
最適化の前に、計測 から始めます。
- Statsウィンドウ: Gameビュー右上の「Stats」で Batches(実質のドローコール数)と SetPass Calls(シェーダー/マテリアル切り替え回数)を確認できます。まずこの2つの数字を覚えておきます。
- Frame Debugger: 「Window > Analysis > Frame Debugger」で1フレームの描画を1ドローコールずつ再生できます。何がどの順で描かれているか、そして 「なぜ前のドローコールとまとめられなかったか」の理由まで表示してくれます。ドローコール調査の本命ツールです。
削減テクニックの使い分け
| 手法 | 対象 | ひとこと |
|---|---|---|
| SRP Batcher | URP/HDRPのほぼ全オブジェクト | 現行の主役。同じシェーダーなら効く |
| スタティックバッチング | 動かないオブジェクト | 効果大。Staticフラグを立てるだけ |
| GPUインスタンシング | 同じ見た目の大量配置 | 草・木・群衆の最終兵器 |
| ダイナミックバッチング | 小さな動くオブジェクト | レガシー。今は基本オフでよい |
SRP Batcher——現行の主役
URP/HDRPでは、まずSRP Batcherが効いているかを確認します。「注文票の枚数を減らす」従来のバッチングと違い、SRP Batcherは注文票1枚あたりの伝達コストを激減させる仕組みです。マテリアルのデータをGPU側に置いたままにするため、同じシェーダー(バリアント)を使ってさえいれば、マテリアルが違っても高速に処理されます。

- 使い方: URPアセット(Universal Render Pipeline Asset)の「SRP Batcher」を有効にします(近年のバージョンでは既定で有効)。
- 注意: 自作シェーダーはSRP Batcher対応の書き方(プロパティを
CBUFFERにまとめる)が必要です。Shader Graph製シェーダーは自動で対応します。 - 確認: Frame Debuggerで「SRP Batch」としてまとまっていれば効いています。
スタティックバッチング——動かないものはまとめて焼く
動かないオブジェクト同士を、ビルド時に1つの巨大メッシュへ結合してしまう手法です。
- 使い方: 背景・建物・地形の小物などを選択し、Inspector右上の「Static」(Batching Staticだけで十分)をオンにします。
- 条件: 同じマテリアルを共有しているオブジェクト同士がまとまります。
- 代償: 結合メッシュを保持する分、メモリ使用量が増えます。モバイルでは効果とメモリのバランスに注意してください。
GPUインスタンシング——同じものを大量に
同じメッシュ+同じマテリアルのオブジェクトを、1回のドローコールで数百〜数千個描画する技術です。森の木、草むら、弾幕、観客の群れなど「コピーの大量配置」で絶大な効果を発揮します。

- 使い方: マテリアルのInspectorで「Enable GPU Instancing」にチェックを入れるだけです。
- 特長: スタティックバッチングと違い、個々のオブジェクトは動けます。位置・回転・色などはインスタンスごとに変えられます。
ダイナミックバッチング——レガシー
動く小さなオブジェクトを毎フレームCPUでまとめる 古い手法です。頂点数の厳しい制限があり、まとめる作業自体がCPU負荷になるため、SRP Batcherが使える現在は基本的にオフで構いません。古いプロジェクトやBuilt-inパイプラインの小物向けの選択肢として名前だけ覚えておけば十分です。
テクスチャアトラス——マテリアルを共有させる下ごしらえ
スタティックバッチングもGPUインスタンシングも、「同じマテリアル」が前提条件です。ところが岩・木・草がそれぞれ別のテクスチャを持っていると、マテリアルも別になり、バッチングのしようがありません。
そこで、複数の小さなテクスチャを1枚の大きなテクスチャ(アトラス)にまとめ、全員が同じマテリアルを共有できるようにします。バッチングの機会を作り出す「下ごしらえ」であり、2Dでは Sprite Atlas として標準機能になっています。

判断基準は1行です。 「Batchesが多いと感じたら、Frame Debuggerで『なぜまとまらないか』を見る」。理由がわかれば、上の4手法のどれで解決すべきかは自然に決まります。
実践:賑やかな森ステージを軽くする
オープンフィールドのアクションRPGの森、タワーディフェンスのマップを埋める小物、レースゲームの沿道の木々——「動かないものが大量にあるシーン」は、どのジャンルでもドローコール削減の効果が最も出やすい場面です。木200本・岩100個・草1,000株の森ステージを例に、手順を通しでやってみます。
- 現状を数える: Gameビューの「Stats」を開きます。仮に Batches: 3,200 だとして、この数字をメモしておきます(効果測定の基準値)。
- 理由を見る: Frame Debuggerで描画を1つずつ再生します。木が1本ずつ別々に描かれ、
Objects have different materials(マテリアルが違う)などの理由が表示されているはずです。ここで原因を確定させてから手を打ちます。 - 動かないものにStaticフラグ: 岩・切り株・柵など、ゲーム中に絶対動かないものを全選択し、Inspector右上の「Static」をオンにします。プレハブなら元を1回直すだけです。
- 同じ見た目の大量配置にGPUインスタンシング: 木と草のマテリアルで「Enable GPU Instancing」にチェックを入れます。風で揺れても問題ありません。
- 残った小物をアトラスでまとめる: ランタン・看板・壺のような細かい装飾が別々のテクスチャを持っているなら、アトラスにまとめてマテリアルを1つに統一しま す。
- もう一度数える: Statsを再確認します。この構成なら Batches: 300前後 まで下がるのが典型的な結果です。見た目は1ピクセルも変わらず、CPU負荷だけが1/10になります。

ポイントは2つです。 「先にFrame Debuggerで『なぜまとまらないか』を確定させる」(推測で手を打つと、効かない最適化に時間を溶かします)と、 「動かないものはStatic、同じ見た目の大量配置はInstancing」 という基本の割り当て。効果の計測を習慣にしたい方は Profilerの使い方 も合わせてどうぞ。
おまけ:先に知っておくと良いこと
- BatchesとSetPass Callsの違い: Batchesは「注文の回数」、SetPass Callsは「調理法の切り替え回数」です。SetPass Callsのほうがコストが重いため、マテリアル・シェーダーの種類を減らすことは常に効きます。
- バッチが切れる典型理由: マテリアル違い・ライトマップの違い・シェーダーバリアントの違い・透明/不透明の混在など。Frame Debuggerが理由を英文で表示してくれるので、そのまま検索すると対策が見つかります。
- オーバードローは 別問題: ドローコールを減らしてもGPU側が重いことがあります。半透明の重なり(オーバードロー)はGPU負荷の代表格で、モバイル最適化 で解説しています。
- LODとカリング: そもそも「描く量を減らす」方向の最適化として、LOD(距離に応じてモデルを簡略化)とオクルージョンカリング(遮蔽物の裏を描かない)があります。ドローコール削減と併用できます。
まとめ
- ドローコールはCPUからGPUへの注文票。多すぎるとGPUではなくCPUが先に詰まる。
- まずStats(Batches / SetPass Calls)とFrame Debuggerで現状把握。推測しない。
- URP/HDRPならSRP Batcherが主役。自作シェーダーは対応記法に注意。
- 動かないものはスタティックバッチング、同じ見た目の大量配置はGPUインスタンシング。
- バッチングの前提はマテリアルの共有。テクスチャアトラスで機会を作る。
「オブジェクトを減らす」前に「注文票をまとめる」——それだけで、同じ物量のシーンが見違えるほど軽くなります。あなたのプロジェクトのStatsウィンドウ、Batchesは今いくつですか?