概要
【TECH x GAME COLLEGE #10】Unityでパフォーマンスの良いUIを作る為のTips
UIはゲームを作る上で必ず通る道で、ゲームの顔と言っても良いです。UnityのUIシステム(通称uGUI)は直感的にUIを作れて便利ですが、UIを好き勝手作ると簡単にパフォーマンスの低下を招きます。
今回は基本に立ち返り、UnityのUIとはどういったシステムなのか、そして最適化する上で確認すべきポイントとTipsを紹介します。
https://techxgamecollege.connpass.com/event/110515/ より引用
講演はUnityTechnologiesJapanの山村さん(テラシュールブログの中の人)
勉強会では、「Unityでパフォーマンスの良いUIを作る為のTips」として下記のようなことを話していただいた
- パフォーマンスの良いUIの為に注意すべきこと
- バッチ
- フィルレート
- リビルド
- その他
講演していただいた資料は後日公開予定とのこと
パフォーマンスの良いUIのためにすべきこと
1. バッチング
- 描画処理 後ろ側から匿名テクスチャを貼り付けていく
- テクスチャ→ マテリアル → ポリゴン の流れをやる
- 同じものを繋げるなら同じことする
- Canvasにまとめて、バッファーを一度作る(バッチング)
- 一括描画できるのは同じテクスチャのみ
- バッチングが効かないとこがある
- ソートレイヤーとして、別々になっていて重なってしまった場合は効かない
- 独自のShaderが違うMaterialが違う場合も効かない
- 座標のZ値が同じいち
- 同じマスクでクリップされていること
- マスクの使用は控える
- UI Profilerで確認する
- どういう風にバッチングされているのかとかがわかる
- バッチ一覧を確認する
- バッチができていない理由がわかる
- SpriteAtlasでまとめてやる
- パックすると入ってほしいものがでる
- 余裕をもって配置する(TightPackingを切る)
- ImageをUseSpriteMeshを使う 2018.3から
2. フィルレート (オーバーレンダリングの話)
- ポリゴンに色を塗るのは1ピクセルづつ塗っていく
- たくさんのUIがあると透明をちゃんと塗っていく
- 何度も透明を塗られる部分がある
- UIProfilerで確認する
- Composite Overdraw で確認する
- 赤くなってるとこはやべえ
- 対策
- 不要なUIを削除
- 重なる部分をできるだけ削る
- SpriteMeshを使用
- FillCenterを外して中央をくり抜く
- オーバードローしても問題ないShaderにする
- AssetBundleの時はShaderの依存関係をちゃんと使う
- Shaderノフかの確認
- 各デバイスのプロファイラーでみれる
- Xcodeで確認できる
3. リビルド
3.1 ジオメトリ
- バッファリングに変化がなければ効率的に使いまわせる
- 変化があれば再構築が必要
- UIをEnable/Disable
- マテリアル変化
- ReactTransformの変化
- Transformの親が変化
- 一つのUIwo変えると同じCanvasの全てのUIを再構築
- メインスレッドはそこまで処理の負荷はない
- Jobの方が辛い
- Rebuildが走っていると山ができる
- 発生させている根本をみる
- CPU Profilerで下記検索
- OnDidApplyAnimationProperties、OnRectTransformDimensionsChange
- 関連オブジェクトの表示
- ちゃんとCanvasを分割する
- バッチングは効かなくなるよ
- 動くUIはImageのSpriteMeshを避ける
- 親UIを動かす
- 全てのバッチが作り直される
- 動かしたタイミングで負荷がかかる
- 要素数を減らす
- 要素をプーリングして最小限のUIでどうにかする
- ScreenSpaceCameraを動かすとやばい
3.2 レイアウトグループ
- Groupの更新は変更時に親を全部GetConponentsを繰り返す
- DirtyするUIが紛れ込むと毎フレームUIのリビルドが走る
- このリビルドはメインスレッドで起こる
- RectTransformに関連するものを操作しない
- LayoutPropertyに関連するものは操作しない
- Mecanimのステートマシンに上記の要素にアクセスするAnimationClipを入れない
- LayoutGroupを可能な限り使わない
4. その他
- RayCastTargetは可能な限り外す
- ついてるだけで負荷がかかる
- WorldSpaceCameraのEventCameraにはカメラを登録する
- FindTag MainCameraが呼ばれる
- PixcelPerfect設定は動かないカメラのみ
- テクスチャは画像解像度にあったものを使う
- 可能な限り圧縮する
まとめ
- 基本的にはUIを動かさない
- 動かすなら最低限の影響を抑える
- 気を抜くな、誰も信用するな、プロファイラを手放すな
質疑応答
- Canvas in Canvas の粒度
- 同時に動くものをまとめていく
- いつからやるの
- ルールをちゃんと決めて作っておく
- フィルレートが一番やばい
- その次にリビルド
- GameObjectのOffはやめた方がいい (バッチが破棄される)
- CanvasGroupのAlphaを0にした方が安いこともある
- CanvasをDisableにすると大きいと辛い
感想
- Unityは何も考えなくてもUI作れてしまうので、あげられたことはほとんど意識していなかった。
- 考えたら当たり前ってこともあるので(オーバーレンダリングとか)、作る時は意識しよう。
- 特に大規模になるとUIの重なりは大変なことになるので、ちゃんと作ることでパフォーマンスアップするね
- Unityのまとめ機能系は、柔軟性に振りまくってるので自前でパフォーマンス作った方がいいよっていう話になったのは面白かった。