UnityのFPSが落ちる問題の対策(描画周り)

Before

とあるアプリのパフォーマンス改善になります。

ベンチマーク対象

CPU:UNISOC T616
GPU:Mali-G57
RAM:3GB
いわゆる格安中華タブ。AntutuV10でGPUが3万未満と、同グレードで比較されるスナドラ680は4万、Helio G99は7万と比較してかなり劣っているのですが、それでも現状30FPSしか出ていないというのが問題。

ちなみにUnityのバージョンは2022.3.15fです。

Profilerでざっくり見る

1フレームの描画に45ms掛かっている場面で、プロファイラで見てもレンダリングにかなりの時間を要していることがわかります。まあCPUの問題ですねこれは

  • MeshRenderer.Skin
    • シーン内でVRMを表示している以上、メッシュの頂点数を減らすとかそういう事をしないと難しそう…?
  • Camera
    • Culling Maskで余計なタグがついているのを消したり、UI用のカメラはAAを無効化する

ただ、このプロジェクトはBRPなので、MeshRendererをなんとかするという点ではURP化するしかなさそう…ということでURP化する。

切り絵になる問題に遭遇したが、UniVRMを消して最新版のUniVRMを入れ直したら解決。

Androidでシェーダー関係でエラー

ランタイムロードでVRMを利用したい時に、アプリビルドに含まれないシェーダーは省略されてビルドされるのが原因。

VRMのランタイム自動ロードではMToonとUniUnlitとURPのLitが使われていたのでGraphics設定のシェーダーリストに追加したら動くようになった。
Litのシェーダーを突っ込むと全てのVariantをビルドする事になる(終わらない)ので、Editorで動かした時のシェーダーのキーワードをFrame Debuggerから確認してShaderVariantを作りましょう。

URP化しただけの状態

URP用のカメラの設定

URP設定でポストプロセス無効化で結構改善

UIを表示するだけのメインカメラが何故か結構重い。
ここでの学びとしては、「Canvasの配下が変更された時に描画が走る」っぽくて、例えば「2Dアプリとしてカメラで何らかの映像をRenderTextureに描画して、それをCanvas内に配置する」場合、RenderTextureの描画ごとにCanvasも描画する事になる。(が、今回はRenderTextureが画面の多くを占めていたので改善しない。)
つまりボトルネックになっているのは、メッシュのスキニングとCanvasのレンダリング処理という事になり、URP化しても改善できるポイントが無いのは当たり前、という事になる。

根本的な改善には至らなかったものの、低スペック端末であえてプロファイリングすることで全体構成の課題が見えてくるというのは勉強になったということでひとつ。

  • 「RenderTextureで別カメラ描画」は描画コストが高いのであまりやるもんじゃない
  • 結局3Dはポリゴン数(特にSkinned Mesh Rendererを入れてる場合)
  • サブCanvasは有効