Kuwapp's Blog

Android と Flutter やってます

【Unity】DrawCallについて調べてみた

DrawCallについての知識が、「少なく抑えておけば軽くなるよ。」ぐらいしかなかったので調べてみた。

DrawCallってなに??

とりあえずUnityマニュアルのドローコール バッチングの欄に軽く目を通してみる。

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

んーよくわからん。
OpenGLとかのAPIにオブジェクト描画して〜っていう命令のこと?

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

つまり、1回のDrawCallでオブジェクトを描画する。複数のオブジェクトを同時に描画する処理をバッチングってことかな。
DrawCallが呼ばれすぎると、オブジェクトを描画する回数が増えて重くなるから、できるだけ1回のDrawCallで複数同時にオブジェクトを描画する(バッチング)ようにすれば軽くなるってことか。

どうすればDrawCallを抑えられるの?

特に自分がすぐに使えそうなところを抜き出してみる。

マテリアル

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

マテリアルはできるだけ共有すればいいということか。

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

バッチングはトータル頂点数が900以下のメッシュでしか適応されません。
一般的にオブジェクトは均一のトランスフォームとスケールを使用すべきです。
リアルタイムシャドウを投影されるオブジェクトはバッチングされません。

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

スタティックバッチングはどんなサイズのジオメトリでもドローコールを減らすことが出来ます。
スタティックバッチングの利用するには、そのオブジェクトがゲーム中、動いたり、回転したり、スケールしたりするということがない ということを明示的に設定する必要があります。
スタティックバッチングはUnity Pro専用

まとめ

DrawCallを抑えるには
・できるだけテクスチャをまとめるなどして、マテリアルを共有する。
・オブジェクトの頂点数を900以下に抑え、オブジェクトを均一のスケールで使用する。
・リアルタイムシャドウを使う場合は、DrawCallに注意する。
・動かないオブジェクトなら積極的にスタティックバッチングを使って軽くする。

なんとなくDrawCallについて理解できた気がする。
モバイル端末ならDrawCallを20以下に抑えるのが目標らしい。
もっと詳しいことはUnityマニュアルのドローコール バッチングに書いてあるので是非。