グラフィックス パフォーマンスの最適化
最適なパフォーマンスのためのキャラクター モデリング

ドローコール バッチング

スクリーンにオブジェクトを描画するために,描画エンジンはOpenGLやDirect3DのグラフィックAPIにドローコール(draw call)を発行しなければいけません。どんな一回のドローコールでも多くのグラフィックAPIの集まりが必要になります。つまりこれはCPUパフォーマンスのオーバーヘッドに重大な影響をもたらします。

Unityはランタイムで複数のオブジェクトを合成し,一回のドローコールで同時に描画します。この処理は「バッチング(batching)」と呼ばれます。Unityがより多くのオブジェクトを一緒にバッチングできれば,レンダリングのパフォーマンスはより良くなるということになります。

Unity内に組み込まれているバッチングは,単なるモデリングツールでのジオメトリ合成(またはStandard Assets packageのCombineChildren スクリプトの利用)以上に,絶大な効果があります。Unity内のバッチングは見える範囲に入った に処理が走ります。描画エンジンはどのオブジェクトも個別にカリング(間引き)しますので,レンダリングされたジオメトリの集合はバッチングしないのと同じになります。一方で,モデリングツールのジオメトリ合成は効果的なカリングを阻害し,結果的に多くのジオメトリをレンダリングすることになります。

マテリアルについて

同じマテリアルを共有しているオブジェクトがバッチング可能になります。そのため,より効果的なバッチングをするには,できる限り違うオブジェクト間で多くのマテリアルを共有する必要があります。

もし二つのテクスチャが違うだけの独立したマテリアルがあるのであれば,二つのテクスチャを組み合わせて一つのテクスチャに合成しましょう( テクスチャアトラス と呼ばれるプロセスです)。いったんテクスチャを同じアトラスにしてしまえば,単一のマテリアルとして使うことができるようになります。

もしスクリプトから共有しているマテリアルプロパティをアクセスするならば,以下の情報が重要です:Renderer.material の変更はマテリアルのコピーが生じます。共有しているマテリアルをキープしたいのであれば,代わりに Renderer.sharedMaterial を使いましょう。

ダイナミック(動的)バッチング

同じマテリアルを共有していて他の条件を満たせば,Unityは自動的に動いているオブジェクトをバッチングします。ダイナミックバッチングは自動的に処理されるので,何かの手間が必要というわけではありません。

ヒント:

  • 動的なオブジェクトのバッチングは 頂点ごとに ある程度オーバーヘッドがあります。ですので,バッチングはトータル頂点数が900以下のメッシュでしか適応されません。
    • シェーダーが頂点位置や法線や一つのUV情報を使っていたら,300頂点までになります。一方で頂点位置,法線,UV0,UV1,タンジェントを使っていたら180頂点までになります。
    • ご注意: この制限値は今後変更されるかもしれません
  • 一般的にオブジェクトは均一のトランスフォームとスケールを使用すべきです。
    • 例外は非均一にスケールされたオブジェクトです。もしいくつかのオブジェクトの全てが異なる非均一のスケールを使用した場合も,まだバッチングすることは出来ます。
  • 違うマテリアルのインスタンスを使用する場合は,基本的に同じものを元にしていても,一緒にバッチングされません。
  • ライトマップを持つオブジェクトは追加のレンダラ マテリアルパラメータを持っています:ライトマップおよびオフセット/スケール。このため,一般的に動的にライトマップされたオブジェクトが全く同一のライトマップの位置でないかぎりバッチングされません。
  • マルチパスのシェーダはバッチングを阻害します。ほぼ全てのUnityの用意するシェーダはフォワードレンダリングで複数ライトをサポートしていますが,それらは効果的に追加のパスを使っています。“追加の ピクセル ライティング” のドロー コールはバッチングされません。
  • リアルタイムシャドウを投影されるオブジェクトはバッチングされません。

スタティック(静的)バッチング

一方でスタティックバッチングはどんなサイズのジオメトリでもドローコールを減らすことが出来ます(動かなくて同じマテリアルを共有することが条件です)。スタティックバッチングはダイナミックバッチングよりも顕著に効果が出ます。CPUパワーを減らす必要があるなら是非スタティックバッチングを選択して下さい。

スタティックバッチングの利用するには,そのオブジェクトがゲーム中,動いたり,回転したり,スケールしたりするということが__ない__ ということを明示的に設定する必要があります。InspectorのStaticチェックボックスをオンにすると,その設定になります。:

スタティックバッチングを使うと,合成したジオメトリ情報を保存しておくためのメモリが余計に必要になります。もしスタティックバッチングの前に,複数のオブジェクトで同じジオメトリを共有しているのであれば,オブジェクトごとにジオメトリのコピーがおこります(エディター上でもランタイムでも)。このことから,いつでもお勧めする方法ではありません。つまり場合によっては,小さいメモリ使用量を維持するために,スタティックバッチングを避けて,レンダリングのパフォーマンスを犠牲になければならないこともあるでしょう。例えば,密集した森林において,木をスタティックにすると,メモリにはかなりの負担になるかもしれません。

スタティックバッチングはUnity Pro専用で,どのプラットフォームでも利用可能です。

その他のバッチングのTips

現在は, メッシュレンダラ および [パーティクルシステム](Particle Systems) のみがバッチングされます。すなわち,スキンメッシュ,クロス,トレイル レンダラおよびその他の種類のレンダリング コンポーネントはバッチング されません

準透明なシェーダはしばしば後方から前方のオブジェクトの順番でレンダリングしないと正しく透明さが機能しないことがあります。Unity は最初にオブジェクトをこの順番でのレンダリングを指令し,バッチングしようとします - しかし順番は厳密に適用する必要がある場合,不透明のオブジェクトと比べてバッチングはより少なくなることを意味します。

Unityのレンダリングの一部はまだバッチングが実装されていません。例えば,シャドウ 投影,カメラのデプステクスチャ,または GUI の場合でのレンダリングはバッチングされません。

グラフィックス パフォーマンスの最適化
最適なパフォーマンスのためのキャラクター モデリング