あなたのモバイルゲーム開発の最適化時間を数ヶ月節約する方法（UI+ロード編）

みなさん、こんにちは。こちらはUWA Technologies（略称UWA）です。
今日は[「あなたのモバイルゲーム開発の最適化時間を数ヶ月節約する方法（レンダリング編）」](https://qiita.com/UWATechnology/items/cf942b051a11179300e2)の続き、次の二パート**「UI」**と**「Loading」**についてご説明いたします。
前回の文章をまだ読まれていない皆様は、是非[こちら](https://qiita.com/UWATechnology/items/cf942b051a11179300e2)へ移動してご覧ください。

#UI
UIパーツの主な問題は、**UIの再構築**です。
UGUIの場合、再構築プロセスは**BuildBatch関数**と**SendWillRenderCanvases関数**にあります。
<img width="1415" alt="1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/391cb921-01a5-24ba-c197-72b328cc0e12.png">
NGUIの場合、再構築プロセスは**UIPanel.LateUpdate関数**にあります。
<img width="1415" alt="2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/dd097550-90b2-37c8-9bac-757c2a73cd66.png">
UI再構築を最適化する方法は？ 一般的な答えは、**「動的ウィジェットと静的ウィジェットを分離して」**ということです。
##静止状態
<img width="1437" alt="3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/cc6040f2-9781-1781-0609-90eb5f28ac68.png">
これは実際のプロジェクトのサンプルです。 プレイヤーをシーン内で静止状態にさせて、何もしません。そうすればUIのコストは非常に安いはずですが、プロファイラーから見ますと、やく2.5 msで、少し高いです。
<img width="1437" alt="4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/fb05d62a-6ad8-43da-c181-2a5a5f4dd042.png">
したがって、UIキャンバスを確認すると、右に示すように、UIメッシュに多数の頂点があることがわかります。
最後に、*これらの絵文字は2〜3秒ごとに移動する*ことが発見されました。 これにより、UIメッシュ全体が再構築されます。 それが原因です。
**絵文字は動的ウィジェットですので、 静的キャンバス全体から分離して、新しいキャンバスに配置する必要があります。** その後、コストが下がれます。
<img width="1437" alt="5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/d6ee590f-a5e8-f5e8-02a3-82e18bd15d9a.png">
プロジェクト「ラグナロク マスターズ」で、プレイヤーをシーン内で静止状態にさせ、何もしません。それとも、コストは1秒ごとに高くなっています。どうして？ それはヒントのせいです。**ヒントは毎秒移動し、大きな静的UIキャンバスにも移動しています。**それらが再構築することを引き起こし、コストも高くなります。
##動く状態
<img width="1437" alt="6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/12029381-74cf-ab67-7b93-24156a8b0a0f.png">
また、プレイヤーが移動すると、右の画像でコストを確認できます。**プレイヤーが移動しながら、緑の円もミニマップで移動していますから、ミニマップ全体を再構築する**ことになります。したがって、全体的な静的UIキャンバスから動的ウィジェットを分離することも最適化できます。

そして戦う時に、
<img width="1437" alt="7.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/c38024b0-eb9c-1c0d-8438-e2e15cd39dd3.png">
<img width="1437" alt="8.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/86099014-9ff6-8b32-cd56-b6441e18889a.png">
コストもとても高いです。 （平均CPUコストは約16msです。）
その原因は**クールダウンマスク**です。 彼らはすべてのフレームを変更し、頻度も高いですから。そこで、彼らを分離して頻度を減らしますと、パフォーマンスを非常に速くなさせます。
##結果
<img width="1123" alt="9.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/97c3c313-9bdf-7319-b7a2-ba6016bf7435.png">
UWA GOTを**17日間**使って最適化した結果、CPU コストは**４msから１.７ms**になりました。

#ロード
ロードも非常に重要であり、何か問題があったらゲームの実行が非常に重くなります。ロードについては、**「リソース管理」**と**「ゲームオブジェクトのインスタンス化」**という二方面に注目してください。
##リソース管理
リソース管理の場合、最初にはローディングAPIです。 Unityエンジンには、**「Resource.LoadとLoadAsync」**、**「AssetBundle.LoadとLoadAsync」**の2つのタイプがあります。
<img width="1437" alt="10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/aefb875d-cdfd-4e99-55ea-cfa57d4a0517.png">
UWAレポートには、**使用されるAPIと詳しい読み込み情報が記録されています**。
<img width="1433" alt="11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/ec0dbce1-98ee-76c5-7392-94da3dec8ebb.png">
例えば、この表には、**「アセット名」**、**「そのタイプ」**、**「どのアセットバンドルから読み込まれたか」**、**「読み込み時間」**、**「詳細な読み込みCPUコスト」**が表示されています。
<img width="1437" alt="12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/20cc26a9-9c70-db49-300e-8085878a4c55.png">
また、**グラフで詳細を確認できます**。 たとえば、この2つのアセットはリソースの読み込みによって、頻繁に読み込まれています。それは問題であり、彼らをキャッシュして再利用する必要があります。そうすればCPUコストも安くなれます。
<img width="1437" alt="13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/0972372a-5ba7-7c49-b2fb-a08b438e3028.png">
3つ目は、**特別なキャッシュです**。 これで、**アセットの正確な読み込みコストがわかります**。
デバイスメモリが不足しているため、すべてのアセットをキャッシュすることは不可能です。キャッシュできるのは、読み込みの長いアセットのみです。 例えば、PKFightwindowは毎回ロードする時に約3秒要ります。**キャッシュに少量のメモリを使用すると、シーンのロードに約3秒節約できて、とても便利です。**
##ゲームオブジェクトのインスタンス化
<img width="1437" alt="14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/6e96c879-f406-c990-bcdb-7bfdff53ed8a.png">
ゲームオブジェクトのインスタンス化について話しましょう。 常にパフォーマンスを向上させるため、インスタンス化は非常に重要です。
UWAレポートには、**Instantiateの詳細なコール情報が記載されています。**
たとえば、*ゲームオブジェクトの詳細な関数名とインスタンス化時間を確認でき、どのゲームオブジェクトに多くのインスタンスが直接生成されているかを確認できます。*
<img width="1417" alt="15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/a8186aca-ef23-8e75-2e19-cc41250d3c3c.png">
また、**インスタンス化の詳細なCPUコストも顕示できます**。 最適化するゲームオブジェクトを決定することは非常に役立ちます。
Common HitやCommon Binddongと同様に、何度もインスタンス化する代わりにキャッシュでき、パフォーマンスが大幅に向上できます。
<img width="1437" alt="16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/29ed59e2-3bc0-5cc5-25d9-e7eac372094e.png">
##結果
ロードの最適化結果は下図のように、**平均FPSは16FPSから26FPSに増えました**。
<img width="1175" alt="17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/06c94df1-e95d-6e93-953e-1cd5c98746f5.png">

---
UWAおよびUWA GOTについてもっと了解したい場合には、[UWA公式サイト](https://jp.uwa4d.com/)に移動してください。
UWA GOTを使っていた[nowsprintingさん](https://twitter.com/intent/follow?original_referer=https%3A%2F%2Fwww.nowsprinting.com%2Farchive%2Fcategory%2FUWA%2520GOT&ref_src=twsrc%5Etfw&region=follow_link&screen_name=nowsprinting&tw_p=followbutton)も自身のブログでUWA GOTについて詳しく説明してしましたが、興味があれば[「やらなイカ？」](https://www.nowsprinting.com/archive/category/UWA%20GOT)に移動してご覧ください。

---
UWA Technologyは、モバイル/VRなど様々なゲーム開発者向け、**パフォーマンス分析**と**最適化ソリューション**及び**コンサルティングサービス**を提供している会社でございます。

UWA公式サイト：https://jp.uwa4d.com
UWA公式ブログ：https://blog.jp.uwa4d.com