ikoan unity 開発メモ

Unityに関するアレコレを日々つづっていこうと思います

uGUIのbatch処理

はじめに

uGUIリリースされてから、一体どれぐらいたったのかわからない。
いままで仕事上ではNGUI使っていたので、逃げていたけれど
ついにuGUI触ってみようかな、と。

環境

Unity2018.5f

前提

unityにはbatch処理というものが存在します。
本当に理解するにはレンダリングに関する基礎知識が必要であるけど、私自身もそこまで至っていないので、簡単に説明しますと。
ゲームの描画とは、CPUから現在のシーン上で表示されるべきオブジェクトの情報をあーだこーだして、GPUに渡してあーだこーだして、最終的な描画情報をバッファに格納し、それをスクリーン上に表示することです。
CPUから渡されるものは、オブジェクトの頂点座標だったり、UV座標だったり、必要なら法線情報や頂点カラーだったり、テクスチャの情報だったり。
それらの受け取って描画するというのがPASS数なり、ドローコール数(厳密には両者は異なる)として数値で表され、過去のUnityではこのドローコール数がアプリケーションの負荷の指標となっていました。(Unity4とかの時代)
ドローコールという数値を減らすには、要はGPUが描画する際にある程度まとまった単位で描画する、という考え方が大事になってきます。
つまり、同一のマテリアル(シェーダーやテクスチャなど)を使用するオブジェクトをまとめて描画する、という考え方ですね。
それがつまりbatch処理になってきます。

「マテリアルAのオブジェクトの手前にマテリアルBのオブジェクト、さらに手前にマテリアルAのオブジェクトを描画する」よりも、
「マテリアルAのオブジェクトの手前にマテリアルAのオブジェクト、さらに手前にマテリアルBのオブジェクトを描画する」方がbatchが効くなら、描画コストが低いわけです。

unityのGUIシステムには当初それがなかったので、NGUIなどを使っていたり、大手の会社は独自の描画システムを構築していたのでしょうけど、uGUIからはbatch処理というものが普通に実装されることになりました。
unityのbatch処理は静的batchと動的batchという2種類が存在します。
まぁそこらへんの違いはググってください。

本題・検証

さて、ここからが本題です。
uGUIのbatch処理はどの単位で行われるのか。
多くのことは一度にはできないので、まずは順番にやって行きます。

  • 2つのCanvasを用意して、それぞれの下には同じテクスチャを使用したImageを配置した場合

SetPass Callsは「2」となりました。
つまり別Canvasではbatch処理は行われないわけですね。

  • 1つのCanvas内で別テクスチャのImageを配置した場合

batch数が増え、SetPass Callsは「1」のままでした。
これはちょっと予想外の挙動ですね。

  • 1つのCanvas内で別テクスチャ、別マテリアルのImageを配置した場合

描画順をA→B→Aのようにしたら、SetPass Callsは「3」になりました。
描画順をA→A→Bのようにしたら、SetPass Callsは「2」になりました。
これは想定内の挙動ですね。
このテストして気づいたのですが、Statisticsのbatchesの数って
batch対象が単一でも1増えるんですね。

  • 1つのCanvas内でPanelを2つ用意し、同一テクスチャのImageをそれぞれに配置

SetPass Callsは「1」となりました。
PanelってNGUIでいうUIPanelなのかなと思ってましたが、挙動としては別なんですね。
というより、Panelオブジェクト作っても、アタッチされるComponentがImageと大差ないので、真価を発揮するのは別のComponentを自前でアタッチした場合なんでしょうか。
なんにしろ、デフォルトのPanelオブジェクトはbatchにはなんら関係なさそうですね。

結果

Canvasが異なるとPass数は増えますが、それ以外では特にマテリアルが一緒な分には問題なさそうですね。
(この結果自体が個人的には少し驚いているのですが)
ただ、スクロールや自動レイアウトなどを実装する際に、ほかのComponentを追加したら挙動は変わるかもしれないので、そこを含めた検証は今後も続けて行きたいと思います。
(というより、テクスチャって違ってもマテリアル同じなら大丈夫なもん?)