オブジェクトをスクリーンに描画するためには、グラフィックス API (OpenGL や Direct3D 等) に対してドローコールが必要です。グラフィックス API はドローコールごとに非常に多くの処理をするため、ドローコールは高負荷で、CPU 側のパフォーマンスオーバーヘッドの原因になります。これは大抵、ドローコール間に状況の変更 (例えばマテリアルの切り替えなど) が発生することに起因し、グラフィックスドライバーで高負荷な検証と 変換処理の原因となります。
Unity では、それに対処するために 2 つのテクニックが使用されます。
手動でゲームオブジェクトをマージするのに比べ、ビルトインのバッチ処理にはいくつか利点があります。特に、ゲームオブジェクトはビルトインのバッチ処理をしても個々にカリングすることが可能です。ただし、欠点もあります。静的バッチ処理では、メモリとストレージのオーバーヘッドを招きます。そして、動的バッチ処理では、いくらかの CPU オーバーヘッドが発生します。
Unityの Player Settings の Other Settings で 、動的バッチ処理と静的バッチ処理を有効または無効にできます。
まとめてバッチ処理できるのは、同じマテリアルを共有しているゲームオブジェクトに限られます。そのため、より効果的にバッチ処理するには、できる限り多くの異なるオブジェクト間でマテリアルを共有するようにします。
もし、テクスチャだけが違う 2 つの同じマテリアルがある場合、これらのテクスチャを合わせて 1つの大きなテクスチャにできます。この処理は、しばしばテクスチャのアトラス化と呼ばれます (Wikipedia の Texture atlases 参照)。いったんテクスチャを同じアトラスにまとめると、1 つのマテリアルとして使うことができます。
共有しているマテリアルプロパティにスクリプトを通してアクセスする必要がある場合は、以下に注意してください。Renderer.material を変更するとマテリアルの複製を作成します。そうでなく、マテリアルを共有したいのであれば、Renderer.sharedMaterial を使います。
シャドウキャスターは、そのマテリアルが異なっていても、レンダリングのときに一緒にバッチ処理を行う事ができます。Unity のシャドウキャスターは、シャドウパスに必要なマテリアルの値が同じである限り、マテリアルが異なっていても動的なバッチ処理を行う事が可能です。例えば、たくさんの木箱には、異なるテクスチャを持つ複数のマテリアルを使用することもあるでしょうが、シャドウキャスターのレンダリングにはテクスチャは関係ありません。そのため、まとめてバッチ処理されます。
ゲームオブジェクトが同じマテリアルを共有し他の条件を満たす場合、動的なゲームオブジェクトは自動的に 1 つのドローコールにバッチ処理されます。動的なバッチ処理は自動的に行われるので、追加の操作は必要ありません。
動的バッチ処理は、CPU 上でゲームオブジェクトのすべての頂点をワールド空間に変換することによって機能します。そのため、動的バッチ処理の処理負荷がドローコールよりも小さい場合にのみ利点があります。ドローコールが実際どの程度の負荷になるかは、多くの要素によりますが、主に、使われているグラフィックス API によるところが大きいと言えます。例えば、コンソールや Apple の Metal のような最新の API では通常、ドローコールの処理負荷がかなり低く、動的バッチ処理を使用する利点が全くないことがしばしばあります。
Unity によって動的に生成されるジオメトリを持つコンポーネントの場合、動的なバッチ処理はメッシュの場合と異なります。
グラフィックスデバイスの呼び出しの負荷を計る場合、コンポーネントのレンダリングの最も遅い部分はマテリアルの設定部分です。ですから、共有する頂点バッファーに異なるオフセットでドローコールを送信すると非常に高速です。
このアプローチは、静的なバッチ処理を使用するとき Unity がドローコールを送信する方法によく似ています。
静的バッチ処理では、静止していて同じマテリアルを共有するジオメトリであれば、どんなサイズのものにでもドローコールを減らすことができます。静的バッチ処理は CPU 上で頂点の変換を行わないため動的バッチ処理よりも低負荷ですが、メモリを多く消費します。
静的バッチを利用するには、そのオブジェクトが静的で、ゲーム内で移動、回転、スケールを行わないということを明示的に設定する必要があります。そのためには、 インスペクターの Static チェックボックスをオンにします。
静的なバッチ処理を行うには、合成したジオメトリを保存するために余分なメモリが必要になります。静的バッチ処理の前に、複数のゲームオブジェクトが同じジオメトリを共有している場合は、エディター上かランタイムのいずれかで各ゲームオブジェクトのジオメトリのコピーが生成されます。これは、必ずしも良い方法とは言えません。なぜなら、場合によっては、メモリ使用量を小さく維持するために、静的バッチ処理を避けて、レンダリングのパフォーマンスを犠牲にしなければならない場合があるからです。例えば、密集した森林において木を静的にすると、かなりのメモリを消費します。
内部的には、静的バッチ処理は、静的オブジェクトをワールド空間に変換し、それらに共有する頂点とインデックスのバッファーを作成することによって可能です。Player Settings で Optimized Mesh Data を有効にしている場合、頂点バッファーを構築するときにシェーダーバリアントによって使用されていない頂点要素はすべて削除されます。 これを実行するための特別なキーワードチェックがいくつかあります。例えば、Unity が LIGHTMAP_ON キーワードを検出しない場合、ライトマップの UV をバッチから削除します。その後、同じバッチ内の可視のゲームオブジェクトのために、状態の変化はほぼなしで一連の単純なドローコールが実行されます。技術的には、Unity はAPI ドローコール分を節約するのではなく、それらの状態の変化 (これが、負荷の高い部分) 分を節約します。バッチ制限は、ほとんどのプラットフォームでは 64k の頂点と 64k のインデックスです (OpenGLES では 48k のインデックス、macOS では 32k のインデックス) 。
現在、メッシュレンダラー、トレイルレンダラー、ラインレンダラー、パーティクルシステム、スプライトレンダラー だけがバッチ処理可能です。つまり、スキンしたメッシュ、クロス、その他のタイプのレンダリングコンポーネントはバッチ処理できません。
レンダラーは同じタイプのレンダラーとしかバッチ処理できません。
半透明シェーダーでは通常、透明度を出すためにオブジェクトを後方から前方の順番でレンダリングする必要があります。Unity は最初に、この描画順をオブジェクトに指示し、その後、それらをバッチ処理します。しかし描画順を厳密に適用する必要があるので、大抵の場合、不透明オブジェクトほど多くのバッチ処理はできません。
互いに接近しているオブジェクトを手動で組み合わせるのも、ドローコールのバッチ処理にはとても効果的な方法です。例えば、引き出しがたくさんある静的な食器棚は、 3D モデリングアプリケーションか Mesh.CombineMeshes を使って、単一のメッシュにまとめることは理にかなった方法といえるでしょう。
2017–10–26 修正されたページ
グラフィックスジョブと互換性のない動的なバッチ処理に関するノートは 2017.2に追加
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.