Unityローディングモジュール詳細分析——Texture編

ゲームやVRプロジェクトの開発中、モジュールのローディング（つまり、「ローディング効率」、「シーン切り替え速度」など）によって生じるパフォーマンスコストとメモリフットプリントは、開発チームにとってよくある問題です。 これにはアセットのローディングコストだけではなく、シーンオブジェクトのインスタンス化やアセットのアンロードも含まれます。開発者からすれば、当該モジュールはUnityエンジンでレンダリングに続いて2番目に大きいモジュールです。 したがって、モジュールのローディングに関する主要な性能問題をここで共有したいと考えています。
[UWAオンライン](https://jp.uwa4d.com)に提出された多数のプロジェクトを統計することで、モジュールのローディングで最も時間のかかるパフォーマンスコストは、アセットのローディング、アセットのアンロード、オブジェクトのインスタンス化、コードのシリアル化等に起因すると考えられます。今回は先にアセットのローディングの中でテクスチャのローディングパフォーマンス分析を行います。

---
#アセットローディング
アセットのローディングは、ローディングモジュールで最も時間かかる部分です。そのCPUコストは、Unityエンジンで主にLoading.UpdatePreloadingとLoading.ReadObjectに反映されます。

Loading.UpdatePreloadingはLoadLevel（Async）のようなインターフェイスが呼び出された場合に現れますが、主に現在シーンのアセットをアンロードおよび次のシーンの関連アセットとシリアル化情報をローディングします。次のシーンの自信のGameObjectとアセットが多ければ、ローディングコストが大きくなります。
>多くのプロジェクトでは、もう一つのローディング方法が存在します。つまりシーンが空のシーンで、ほとんどのアセットとGameObjectsは、OnLevelWasLoadedコールバック関数によってローディング、インスタンス化、combinemeshインタフェースに呼び出されます。この場合は、Loading.UpdatePreloadingのローディングコストは小さくなります。

Loading.ReadObjectは、アセットがローディングの実際のアセット読み取りパフォーマンスコストです。基本的に、Unityエンジンの主要なアセット（テクスチャ、グリッド、アニメーションなど）はこれによって読み取られます。この項目は、プロジェクトシーンの切り替え効率を大きく左右すると言えます。このため、現在のプロジェクトで使用されている主流のアセットについて多くの試験と分析を実施しており、開発中のプロジェクトにお役に立てるように以下に分析結果を共有します。

**注意事項：現在、UWAオンラインにはモバイルプラットフォーム向けのゲームプロジェクトが90％以上のため、この記事のアセットパフォーマンス分析は主にモバイルプロジェクトを対象としています。したがって、モバイルデバイス上の各アセットのローディングパフォーマンスを最初に分析および要約します。**

---
#アセットローディングパフォーマンステストコード
以下は、テストで使用したテストコードです。各アセットを特定のサイズのAssetBundleファイルにし、次のコードを使用して1つずつ異なるデバイスでローディングし、異なるハードウェアデバイスでのアセットローディングパフォーマンスの比較結果を取得します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/5ffc1c89-f76a-5a7b-cdd2-163283ec37d5.png)

**テスト環境**

Unityエンジンバージョン：Unity 5.2
テスト対象デバイス：5つの異なるグレードのモバイルデバイス（Android：Redmi2、RedmiNote2、およびSamsungS6，iOS：iPhone 5 と iPhone 6）

---
# テクスチャアセット
テクスチャアセットは、プロジェクトのローディングプロセスで最も高コストのアセットの1つであり、そのローディング効率はそれ自体のサイズによって決まります。 現在、テクスチャアセットのサイズを決定する3つの主な要素があります：解像度、フォーマット、およびMipmapが有効かどうか。
##1.  解像度とフォーマット
これら2つの項目の設定はテクスチャアセットのサイズに大きな影響を与えるため、解像度とフォーマットはテクスチャアセットの読み込み効率に影響する重要な要素です。 したがって、これら2つの要素を詳細にテストしました。
###テストケース1：同じフォーマットと異なる解像度でのローディング効率テスト

解像度2048×2048の2つの一般的なテクスチャアセットを選択し、AssetBundleを設定するときに、最大解像度を512×512、1024×1024、および2048×2048に設定し、テクスチャフォーマットをETC1（Android）とPVRTC（iOS）に設定しました。 そして、Mipmap機能を無効にしています。 したがって、3セットのテクスチャのメモリ使用量はそれぞれ256KB、1MB、4MBであり、対応のAssetBundleサイズは156KB、531KB、1.92MB（Androidプラットフォームの場合）、175KB、628KB、2.4MB（iOSプラットフォームの場合）です。 Unityバージョンは5.2で、圧縮形式はデフォルトのLZMA圧縮です。

Androidプラットフォームテストテクスチャ：
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/b77e172d-6c9c-6998-6f28-f02d1d3f4758.jpeg)
これらのテクスチャアセットを5つの異なるグレードのデバイスにローディングし、偶然性を下げるために、各デバイスでローディング操作を10回繰り返し、最終的に平均値をパフォーマンスコストとします。具体的なテスト結果を以下の表に示します。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/697de706-aad4-acab-3cc2-86c0e32ff84d.png)
**上記のテストにより、次の結論を得ることができます。**
> 1.  テクスチャアセットの解像度は、ローディングパフォーマンスに大きな影響を与えます。解像度が高ければ高いほど、ローディングに時間がかかります。デバイスの性能が悪ければ悪いほど、処理時間の差は顕著に現れます。
2.  デバイスの性能が良ければ良いほど、ローディング効率はよくなります。ただし、ハードウェアでサポートされるテクスチャ（ETC1 / PVRTC）の場合、ミッドエンドデバイスとハイエンドデバイスのローディング効率の違いはすでに小さく、たとえば、図のRedmiNote2とSamsung S6デバイスはそれほど違いがありません。

###テストケース2：異なるフォーマットと同じ解像度でのローディング効率テスト

解像度1024×1024の2つの一般的なテクスチャアセットを選択し、AssetBundleをフォーマットするときに、異なるプラットフォームに応じて、パッケージ用のテクスチャフォーマットを異なるフォーマットに設定しました。 Androidプラットフォーム向けではETC1、ETC2、RGBA16、RGBA32を使用し、iOSプラットフォーム向けではPVRTC 4BPP、RGBA16、RGBA32フォーマットを使用し、同時にテクスチャごとにMipmap機能を無効にします。したがって、3セットのテクスチャのメモリ使用量は1MB、1MB、4MB、8MB（Androidプラットフォーム）/ 1MB、4MB、8MB（iOSプラットフォーム）です。

Androidプラットフォームテストテクスチャ：
![4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/256acbd4-70d1-4c10-7d2a-d5728e01cc70.jpeg)
テストケース1と同様に、5つの異なるグレードで10回のローディング操作を繰り返し、最終的に平均値をパフォーマンスコストとしました。 具体的なテスト結果を下図に示します。

**Androidデバイス：**
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/a4ba5864-44c8-9b0f-a87b-c0fa78907628.png)
**iOSデバイス：**
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/e6117f0a-c4aa-a7aa-cef8-6965f20c4523.png)
上記のテストにより、次の結論を得ることができます。
> 1.  テクスチャアセットのフォーマットはローディングパフォーマンスに大きな影響を与えます。Androidプラットフォームでは、ETC1とETC2のローディング効率が一番高いです。同様に、iOSプラットフォームでは、PVRTC 4BPPのローディング効率が最も高いです。
2.  RGBA16のテクスチャのローディング効率もRGBA32フォーマットと比較して非常に高く、そのローディング効率はETC1 / PVRTCに非常に近く、デバイスが優れているほど、ローディングコストの差はそれほど明確ではありません。
3.  RGBA32のテクスチャのローディング効率は、ハードウェアデバイスのパフォーマンスに大きく影響されますが、ETC / PVRTC / RGBA16はハードウェアデバイスの影響をあまり受けません。

**注：テストで使用したETC1およびETC2テクスチャはすべてRGB 4Bitフォーマットであるため、半透明のテクスチャマッピングには2つのETC1形式のテクスチャが必要です（1つのRGBチャネル、もう1つのAlphaチャネル）。 2つのETC1のテクスチャを随一読み込むと、ローディング効率はRGBA16フォーマットよりも低くなりますが、ロード方法で補正できます。これについては、後続の記事で詳しく説明します。**

##2.  Mipmap機能を有効に
Mipmap機能をオンにすると、テクスチャの一部のサイズも大きくなり、一般に、メモリは元のサイズの1.33倍に増加します。したがって、Mipamp機能を有効にする前後のローディングパフォーマンスをテストしました。

テストケース3：Mipmap機能のローディング効率テストのオン/オフを切り替えます

ETC1、PVRTC、RGBA16フォーマットおよびRGBA32を使用して、解像度が1024×1024の2つの一般的なテクスチャアセットを使用します（テストで使用されるテクスチャはテストケース2と同じです）。AssetBundleに設定する際に、１セット目をMipmap機能をオンにして、もう１セットのMipmap機能をオフにします。

テストケース1と同様に、5つの異なるグレードで10回のローディング操作を繰り返し、最終的に平均値をパフォーマンスコストとしました。具体的なテスト結果を下図に示します。

**Androidプラットフォーム：**
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/1492136d-8d82-2bf0-7577-308d0bbb6366.png)
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/b5f901f1-7355-ce48-7efa-83dcd84c31d3.png)
**iOSプラットフォーム：**
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/52d63a49-9b9e-d565-5a21-eaa3b0ca6c9a.png)
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/c1525cf4-3c61-cb81-a4ba-ed93b37aa894.png)
上記のテストにより、**Mipmap機能をオンにしたことによりアセットのローディングに時間がかかり、デバイス性能が低いほど、ローディング効率の影響が大きくなることがわかります。**

上記のパフォーマンステストを通じて、テクスチャアセットを読み込むための推奨事項は次のとおりです。
>1.  RGBA32およびARGB32テクスチャの使用を厳密にコントロールし、視覚効果を確保するという前提下で、「ギリギリで十分」という原則に基づいて、テクスチャアセットの解像度を下げ、ハードウェアでサポートされるテクスチャフォーマットを使用します。

>2.  ハードウェアフォーマット（ETC、PVRTC）が視覚効果を満たせない場合、RGBA16フォーマットは比較的によいオプションであり、視覚効果を高めることもでき、ローディング時間も短縮することもできます。

>3.  UIテクスチャのMipmapが有効になっているかどうかに特に注意しながら、テクスチャアセットのMipmap関数を厳密にチェックします。 UWAで評価されたプロジェクトの中で、プロジェクトのUIテクスチャの多くがMipmap機能を有効にしました。これにより、メモリ使用量が無駄になるだけでなく、ローディング時間も長くなります。

>4.  ETC2は、OpenGL ES3.0をサポートするAndroidモバイルデバイスの半透明テクスチャフォーマットを処理するための良いフォーマットです。ただし、ゲームを多数のOpenGL ES 2.0デバイスで実行する必要がある場合は、ETC2のテクスチャを使用することはお勧めしません。大量のメモリ（RGBA32へのETC2）が発生するだけでなく、読み込み時間も長くなるためです。次の図は、Samsung S3およびS4デバイスのテスト2で使用されたテストテクスチャのパフォーマンスを示しています。 OpenGL ES2.0デバイスでは、ETC2フォーマットのテクスチャがETC1フォーマットよりも大幅に高く、RGBA16フォーマットのテクスチャよりもわずかに高いことがわかります。そのため、開発チームがプロジェクトでETC2フォーマットのテクスチャを慎重に使用することをお勧めします。
![11-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/3a3b6ee0-f9f8-f2e6-e05c-8ca3a4ab977f.png)

**開発チームが関連する情報列を並べ替えるだけでアセット使用量をすばやく確認できるように、検出された各テクスチャリアセットパラメーターの詳細表示をUWA評価レポートに含めたのは、上記のローディング効率の問題のためです。 パフォーマンスの問題を引き起こしている特定のアセットを見つけることができます。**
![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/62dd4b71-b1b1-3d6e-390a-d27e6713a9ed.png)

**説明：上記は、テクスチャアセットのローディング時のパフォーマンステストです。 テストデータは、当社が使用するテストテクスチャの読み込みデータです。コンテンツの違いによりAssetBundle圧縮パッケージのサイズが異なり、最終的な読み込み効率が異なるため、異なるテクスチャの読み込み効率が異なることに注意してください。 ここでは、特定のパフォーマンス比較を行います。意図は、ローディングパフォーマンスに対するテクスチャフォーマット、解像度、およびMipmap関数の影響を誰も直感的に理解できるようにすることです。**

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

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