この記事でのバージョン
Unity 2018.2.17f1
はじめに
UnityでUIを実装するための機能であるuGUIは、以下のような仕組みを持っています。
どうもCanvasは一度Canvas内のUI(CanvasRenderer)を収集しビルドする(一つのメッシュ化する)事でパフォーマンスの最適化を図っているらしく、1個でもUIが動くとCanvas内のUIを再収集して作り直し…といった事を行うみたいです。このため、常に動いているUIが含まれている場合、これが高いコストになるケースが有ります。
つまり、uGUIはCanvas単位で最適化を行っているので、
「ショップUIもバトルUIもポーズUIも全て同じCanvas内に配置」し、
「そのCanvasのUIを頻繁に動かしたり、変更したりする」みたいな状況だと重くなります。
逆に言うとCanvasを適宜分割したり、UIの変化を抑えたり、
頻繁に変化するUIのCanvasを分けたりすると軽くなるという事でもあります。
今回はこの「uGUIは頻繁に動かしたり、変更したりすると重くなる」というのが
具体的にどの程度重くなるのか数値で確かめてみた感じの記事です。
なお、記事中の画像は以下のアセットを使っております。
HD Icons Pack Vol.1 | 2D Icons | Unity Asset Store |
比較内容
今回は大量の画像をuGUIのImageまたはSpriteRendererで表示し、
それを動かさない場合と、一つだけ動かした場合についての比較を行いました。
(全て動かした場合は両方とも負荷が増しただけで、比較結果に影響がなかったので割愛)
また、評価にはFPSの平均(300フレーム)を使いました。
ただし、起動時に大量の画像を生成し処理落ちが発生するため、
起動してから数十フレーム経過させてからFPSの計測を開始するようにしました。
なお、FPSの表示にもuGUIのTextを使っていますが、TextのCanvasとImageのCanvasは分けてあります。
(ImageのCanvasは全て同じ)
ちなみに今回はMac用にappをビルドして、実機上での比較を行いましたが、
プラットフォームやUnityのバージョン、PCの性能によって結果の数値は大きく変わるはずです。
(おそらく結果の優劣が変わる事はないはず)
比較結果
実際に比較を行い、FPSの平均(低いほど負荷は大きい)をまとめたものが以下の表とグラフになります。
なお、SpriteRendererで画像を表示した場合は2D、
画像を動かさない場合は静止、一つだけ画像を動かした場合は運動と表記してあります。
また、FPSが0のものは重過ぎて計測不能だった場合です。
画像の数 | uGUI : 静止 | uGUI : 運動 | 2D : 静止 | 2D : 運動 |
---|---|---|---|---|
1000 | 60.02 | 60.05 | 60.05 | 60.04 |
2000 | 58.99 | 59.33 | 59.98 | 60.05 |
3000 | 60.04 | 29.97 | 60.06 | 60.05 |
4000 | 60.05 | 19.70 | 60.00 | 60.03 |
5000 | 60.05 | 14.53 | 60.01 | 60.05 |
10000 | 60.04 | 4.12 | 60.05 | 59.84 |
20000 | 59.95 | 0.00 | 57.44 | 57.16 |
30000 | 59.73 | 0.00 | 32.01 | 29.82 |
40000 | 50.28 | 0.00 | 25.79 | 27.11 |
50000 | 40.42 | 0.00 | 17.68 | 18.87 |
100000 | 18.54 | 0.00 | 10.42 | 10.52 |
グラフを見てもらうと一目瞭然ですが、
画像を動かさなかった場合はuGUIの方が軽く、動かした場合はuGUIの方が重い
という最初に述べた通りの結果になりました。
また、uGUIで画像を動かした場合のFPSの減少具合を見れば、
「uGUIの使い方を誤ったり最適化を怠ったりすれば、簡単に処理落ちに繋がる」
という事も理解しやすいかと思います。
ちなみに今回は画像を何千、何万と表示しましたが、
実際のゲームでは画像表示以外の処理もたくさんあるため、
「ここまで画像を表示せずとも処理落ちに繋がる場合がある」という点には注意が必要です。