【Unity】UI最適化Tips
Unityの最適化Tips「UI編」です。公式の最適化TipsであるSome of the best optimization tips for Unity UI – Unity で公開されているTipsの内容を確認しながら僕なりに検証してみます。重いアプリは大体、基本的な部分が出来ていないことが多いです。
目次
環境
- 確認バージョン 2018.3.8f1
Canvas を分ける
UnityのUIシステムはCanvas単位で更新(Rebuild処理)がかかるので、動くUIはCanvasを分けた方が良いという話。
ObjectAもObjectBも並列に配置する
Canvas
|_ObjectA
|_ObjectA
|_ObjectA
|_ObjectB // アニメーション再生
アニメーションさせるObjectBにCanvasをはさむ
Canvas
|_ObjectA
|_ObjectA
|_ObjectA
|_Canvas
|_ObjectB // アニメーション再生
それぞれProfilerで処理負荷を確認してみます。ObjectAを1000個程度配置しています。
ObjectBを同じCanvasに配置して実行したとき
ObjectBを異なるCanvasに配置して実行したとき
前者はRenderOverlaysの数値が高く描画負荷が高くなっています。
Canvasを分けた方が差分で描画されるため軽くなります。ただし、Canvasが別なので同じSpriteAtlasを使用していてもPass Callが分かれます。Profilerで確認しながら対応するのが良いと思います。
そもそも動くUIとは何か?ですが、アニメーションによるPositionを変えたりは勿論のこと、ActiveのON/OFFやColorの変更も対象となります。シェーダーでUVを移動させたりしても同様です。
Canvasを分けるかどうかの基準は「頻繁に動くものがあるかどうか?」で良さそうです。
Camera.main の使用を避ける
MainCameraを参照したい時はMain.cameraを直接見るのではなくキャッシュして使いまわす。そしてCanvasのRenderModeが「World Camera」である場合は必ずCameraを設定する様にする。
「World Camera」のカメラ設定がNoneの場合
カメラに何も設定されていなくても、Canvasがイベントを受け取るためメインカメラを探そうとする。
unity3d-ui/GraphicRaycaster.cs at master · tenpn/unity3d-ui · GitHub
public override Camera eventCamera
{
get
{
if (canvas.renderMode == RenderMode.ScreenSpaceOverlay
|| (canvas.renderMode == RenderMode.ScreenSpaceCamera && canvas.worldCamera == null))
return null;
return canvas.worldCamera != null ? canvas.worldCamera : Camera.main;
}
}
Canvas毎に毎フレーム検索するため、塵も積もればそれなりのCPU負荷となります。
可能な限り Layout Group を回避する
Vertical Layout Groupなどを使用して子オブジェクトを配置する場合、頻繁に呼ばれる場合、なるべく使わない様にして、出来る限りアンカーの設定で済ませる。要素数が動的に変化するレイアウトでも、個人的に自動レイアウトをやめるのは、現実的な解決方法ではない気がするので、自動レイアウトのイベントがマイフレーム発火することの無い様、気を付ける程度で良いと思います。
賢いやり方で UI オブジェクトをプールする
はじめの「Canvasを分ける」でほぼ解決するので割愛。Canvas.Rebuildの範囲を絞りましょうという話です。
Canvas を非表示にする方法
gameObject.SetActive(false)ではRebuildが走ってしまうため、非表示にしたい時はCanvasコンポーネントを無効化します。描画されなくなるだけで、再びCanvasコンポーネントを有効すると再構築も走らず良いです。
UI 要素上でアニメーターを最適利用する
Animator再生中「動くUI」に該当します。値の変化が無いIdle中のアニメーションを再生している場合でも該当するため、無駄なアニメーションは再生しない、またはCanvasを分けるといったアプローチが必要です。
まとめ
ほとんどの場合、この辺りを守って実装すればパフォーマンスは保てると思います。もちろん、他にもフィルレートを抑える方法など沢山ありますが、まずは公式のTipsに則って最適化してみるのが吉だと思います。