PCでAnimationClipの読み込みが遅い問題


##問題
プロジェクトでは、アニメーションのFBXメッシュの冗長性の問題を解決するために、アニメーションを切り出す対策を講じましたが、この問題を解決すると同時に、新たな問題も発生しました。つまり、これらのアニメーションはPCでの読み込みに非常に時間がかかります。

##原因
これは主にUnityのアセット管理メカニズムに関連しています。

##解決
Unityについて知っておくべきいくつかのこと：

1、UnityEngine.Objectから継承されたすべてのオブジェクトは、Unityでシリアル化できます。

2、Unityのシリアル化は複数の形式をサポートします。最も一般的に使用されるのは、読みやすいYamlテキスト形式です。パッケージ化後、Unityはパフォーマンスが向上したバイナリ形式に変換されます。 Unityは、バイナリシリアル化ファイルをテキストシリアル化ファイルに変換するためのツールを提供します。 Unityのインストールディレクトリ（例：D:\Program Files\Unity2018.4.0f1\Editor\Data\Tools\binary2text.exe）にあります。

3、エディターのデフォルトのシリアル化形式はテキスト形式であり、バージョンのマージに便利です。エディターの設定で変更できます。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/ffe43e74-015a-1cb2-fdc6-b12418b06c8e.png)



4、Unityのアセットインポート操作は、実際には、アセットソースファイルに従ってUnityに対応するObjectオブジェクトを生成し、それをLibraryディレクトリにシリアル化することです。Unityによって認識されるすべてのアセットがインポートされると、UnityはUnityの内部オブジェクト（Mesh、Texture、AnimationClip…）に変換されます。

5、Unityのアセットの読み込みは、実際にはこれらのシリアル化されたファイルを逆シリアル化することです。

6、UnityはFBXをPrefabとして扱います。

7、インポートされたアセットファイルごとに、UnityはGUIDを生成し、このGUIDを同じ名の.metaファイルに保存します。例：
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/90da981b-2a01-0e00-a683-633f483945da.png)



8、このGUIDを使用して、アセットファイルに対応するUnityオブジェクトのシリアル化ファイルを見つけることができます。方法は次のとおりです。上記のように、GUIDの最初の2桁を取得します。例えば、上記のように、プロジェクトディレクトリの「Library\metadata」で「ae」と呼ばれるディレクトリを検索し、そしてGUIDと呼ばれるバイナリシリアル化ファイルが検索できます。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/0316dda4-229a-f2de-fd10-021695e14053.png)



次に、この問題を再現するために、実験を行いましょう。

1）最初にアニメーション付きの4つのFBXファイルを準備し、次にProjectパネルでCtrl + Dを押すとFBXのアニメーションが1つずつ切り出されます。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/4cbff478-f2ee-765b-de4d-65cfbe876da8.png)



2）2つのPrefabを作成し、それぞれfbx_animとstd_animという名を付けます。 fbx_animのAnimationコンポーネントは、4つのFBXのAnimationClipを参照します。 std_animのAnimationコンポーネントは、4つの切り出されたアニメーションファイルを参照します。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/8bfbd1fc-66b8-7fcf-2cf1-7929dcbece70.png)



3）テストスクリプトを作成し、ゲームを起動してテストします。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/f2f11108-c630-37b3-f6f8-889106c892c1.png)



4）バイナリ形式とテキスト形式が読み込みパフォーマンスに与える影響を理解するために、2つの形式で別々に実験を行い、各実験には10グループの読み込み時間データ（単位：ms）を抽出します。比較は次のとおりです。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/d18178ec-a912-c43d-75c4-43411ea82839.png)



テキスト形式の場合、切り出されたアニメーションの読み込み時間はFBXの50倍以上であるのに対し、バイナリ形式の場合、平均時間はFBXの約2倍であることがわかります。



**Ｑ：FBXからAnimationClipを切り取った後、ロードに時間がかかるのはなぜですか？**

1）上記のanim_1.animを例にして見ましょう。まずUnityのLibraryには、切り出されたAnimationClipがどのようになるか確認しましょう。

そして、コマンドを実行して、anim_1.animに対応するシリアル化されたファイルをテキスト形式に変換します。
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/7a61c887-c1f3-ecbf-cb81-effa908401a9.png)
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/beec6542-7487-5c4a-8039-db41771711ad.png)





開いた後、このシリアル化されたファイルがアニメーションの曲線データを保存していないことがわかります。代わりに、アニメーションソースファイル「Assets / Animatoins /anim_1.anim」を指します。

２）次に、anim_1.fbxに対応するシリアル化されたファイルを見つけます。

![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/636223ea-02aa-5fa2-ca20-7fc7f6d2ce77.png)
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/a2e4cf0f-2a20-fd72-60d3-cc68cc460051.png)
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/c39a7a8a-23ff-0fe2-05ca-234ba21f4955.png)

ご覧のとおり、AnimationClipオブジェクトのシリアル化されたデータを格納する曲線データ、およびその他のオブジェクトのシリアル化されたデータ（Mesh、GameObject ...）が含まれています。

非AssetBundleモードを使用してPCで実行しますと、プロジェクトのアセット読み込みインターフェイスは、UnityのAssetdatabase.LoadAssetAtPathを使用しています。上記から、AnimationClipがFBXにある場合は、シリアル化されたバイナリファイルが読み込まれ、.animの独立した形式として存在する場合、Unityはシリアル化されたバイナリファイルではなくアニメーションソースファイルを直接読み込むことが分かりました。Unityのデフォルトのシリアル化形式の設定はテキスト形式であるため、非常に遅くなります。

**Ｑ：では、Unityが切り出されたアニメーションを最終形態のバイナリシリアル化形式に保存しないのはなぜですか？**

A：これは、FBXのAnimationCipが読み取り専用であるのに対し、独立した.animファイルは編集可能であるためです。Unityが.animファイルを最終形態のAnimationClipオブジェクトシリアル化ファイルにリアルタイムで変換する場合、編集の体験が悪くなるかもしれません。そのため、Unityはパッケージ化時にのみAnimationClipオブジェクトのシリアル化ファイルに変換します。

**Ｑ：では、この独立したアニメーションソースファイルと最終的なアニメーションファイルの違いは何ですか？**

A：上記の方法に従って、anim_1.fbxに対応するシリアル化されたファイルを見つけ、AnimationClipのシリアル化されたデータをコピーして別のファイルに入れ、anim_1.txtという名を付け、anim_1.animとDiff比較を実行します。
![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/68dc196b-f27b-4776-fea7-09f3bad20a2e.png)



ご覧のとおり、両者にはいくつかの変数は同じですが、曲線データの構成形式は完全に異なります。アニメーションソースファイルのデータ構成形式は編集にさらに役立ち、最終リリースバージョンのAnimationClipはランタイムにさらに役立ちます。ソースファイルを直接ロードするには、データ形式の変換が必要で、これはCPUを消費します。

独立したアニメーションファイルの読み込みは遅くなるもう1つの重要な理由は、.animファイルをAnimationエディタで開いて変更して保存した後、Unityがエディタでのみ使用される大量のデータを挿入することです。
![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/dc23d69a-f6dc-26b4-c453-37a8319fa865.png)

![15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/907f8866-77af-322f-c4c7-9cc84e6dbee2.png)




Animationエディタで編集した後、Unityは大量のデータを挿入し、ファイルサイズは元のサイズのほぼ4倍であることがわかります。これらのデータはエディターでのみ使用され、パッケージ化後に削除されますが、エディターでゲームを実行すると、これらのデータによってアニメーションファイルの読み込みが遅くなります。次の一連の実験データは、この結論を検証することができます。

小さな変更を加えた後、4つの切り出されたアニメーションを保存し、上記のテスト環境を使用して一回のテストを実行します。得たデータは次のとおりです。
![16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/805da6fd-aafd-b486-561a-8c4b88876fa4.png)



実験データから、エディターで開いて保存したアニメーションファイルの読み込みが遅くなることがわかります。テキスト形式の場合、独立したアニメーションファイルのロード時間はFBXの150倍以上に達しました。バイナリ形式の場合、平均ロード時間はFBXのほぼ3倍です。

**Ｑ：では、この問題をどのように解決するのですか？**

A：上記の実験データから、シリアル化形式が.animアニメーションファイルの読み込み速度に最大の影響を与えることが分かりました。

アニメーションファイルをバイナリ形式で設定すると、この問題が大幅に軽減されます。ただし、プロジェクトのシリアル化形式を「Force Binary」に直接設定するだけでは不十分です。実際のプロジェクト開発では、常に複数の人が同じアセットファイルを変更する状況に置かれます。強制的にバイナリ形式に変更し、変更をマージする時に、とても面倒なことになってしまいます。また、Unityには、特定のアセットをバイナリ形式で設定するだけのオプションはありません。 Unityが提供するもう1つのオプションは「Mixed」です。このオプションは、プロジェクト内の既存のシリアル化形式を保持し、新しく作成またはインポートされたアセットはバイナリ形式を使用します。これも、この問題の良い解決策ではないようです。これは確かにジレンマであり、ちょっと解決できないようです。

**一つ考えられる方法は、同じプロジェクトの2つのコピーをローカルに保存することです。一つはエディターでの開発とテストのためにバイナリ形式に設定され、もう一つのプロジェクトはバージョンライブラリと同期されます。ローカル開発が完了したら、差分ファイルを同期プロジェクトにインポートして提出します。**（プロジェクトがエディターにゲームをロードする場合、それはすでに耐えられないほど遅ければ、その方法を検討することができます。）

##まとめ
アニメーションがFBXから独立した.animファイルにカットされた後、これは「読み取り専用アニメーション」から「読み取り・書き込みアニメーション」へのプロセスです。

独立したアニメーションファイルと最終的にリリースされたアニメーションファイルのデータ形式は異なり、Unityはパッケージ化時に変換します。エディターでゲームを実行して、FBXでのアニメーションファイルを使用する場合、Unityは最終リリースしたアニメーションシリアル化データを直接ロードします。これらのデータはFBXがプロジェクトにインポートされた時に生成されるため、非常に高速です。独立した.animファイルを使用している場合、Unityはアニメーションソースファイルをロードします。これにはデータ形式の変換が必要です。テキスト形式のシリアル化されたファイルも、逆シリアル化時に非常に遅くなます。それに、Animationエディターでアニメーションを編集して保存した後、Unityはまた、このアニメーションファイルに元のデータ量の3倍を挿入します。アニメーションファイルの読み込み速度の足を大幅に引っ張ります。

プロジェクトリンク：https://pan.baidu.com/s/1CYCNWw2TZLgtKWNUY5AuAA

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

今なら、UWA GOTローカルツールが**15日間に無償試用**できます！！
よければ、ぜひ！

UWA公式サイト：https://jp.uwa4d.com
UWA GOT OnlineレポートDemo：https://jp.uwa4d.com/u/got/demo.html
UWA公式ブログ：https://blog.jp.uwa4d.com