【Unity】Canvasでパフォーマンスに関わることについて調べてみた
はじめに
今後UI周りに広く関わることになったので、Canvasに関して気になってはいたけど調べていなかったことについて調べてみました。
目次は以下です。
CanvasとSpriteAtlasの関係
はじめに、SpriteAtlasでまとめたSpriteを使うUIを複数Canvasに分ける場合と分けない場合でDrawCallにどんな違いが出るのかを調べました。 SpriteAtlasに関してはこちらを参照してください
描画したUIは以下のようなものです。 表示されているものをすべて一つのSpriteAtlasにまとめました。
これらのことから、アトラス化により各UIで使われるSpriteが一つのSpriteAtlasになっていたとしても、Canvasが分かれていては別途DrawCallが発生してしまうことがわかります。 SpriteAtlasとして効果を発揮するならば、複数Canvasを用いてUIを構成する場合はCanvasごとにアトラス化するのが良さそうです。
動くUIと動かないUIでCanvasを分ける
先程の例をみるとCanvasを分けることにはデメリットしかないように見えますが、UnityのCanvasの仕様上Canvas内に一つでも動くUIが存在するとCanvas全体にRebuild処理が走り結構な負荷がかかるそうです。 そのため、動くUIと動かないUIに関してはCanvasを分けるべきだと言われています。
今回は、実際に動くUIと動かないUIを分割する場合としない場合でどれくらいの差があるのかを調べてみました。
動くUIとしてx方向にscaleするアニメーションをしたImageを、動かないUIとしてただのImageを用意しました。
差を見ると分かる通り、動くUIが一つあるだけでUI全体に対して描画の更新がかかっているようです。
また、動くUIとはなんなのか曖昧だったので試してみたところ、ImageのColorを変えたり、enableを変更するだけでも更新がかかるようでした。
大きく分けるならば、常時動いているようなUIとたまに動くUIと全く動かないUIをそれぞれ3つのCanvasに分けてやるのが良さそうです。
まとめ
Canvasは分けすぎても良くないし、分けなくても良くないことがわかりました。 基本的には、常時動くUIとたまに動くUIと動かないUIでCanvasを分けて、それぞれでアトラス化をしてやれば良さそうです。
Profilerをあまり使い慣れていなくて計測が雑なので、もしもっと詳しく計測できる方法や間違っていることがあれば教えてください。
(追記) DeepProfileによる検証し直し
動くUIと動かないUIをCanvasとして分ける場合と分けない場合の違いについての計測で、DeepProfileを用いて計測し直した結果を残しておきます。
- 動くUI × 1 と 動かないUI ×1000を同じCanvasにしたとき
DeepProfileのCalls
DeepProfileのHierarchy
- 動くUI × 1 と 動かないUI×1000を別のCanvasにしたとき
DeepProfileのCalls
DeepProfileのHierarchy
DeepProfileで計測した結果が上記のようになりました。 動くUIを分けなかった場合、WaitForJobGroupIDで非常に時間がかかっていることがわかります。 実際は1000個も同じCanvasにUIが存在することは殆どないと思いますが、分けると分けないとで処理時間がかなり変わってくることがはっきりとわかったのでやっぱり分けたほうが良さそうです。