Unityアセット管理に関して、あう可能性のある問題——アセット管理編(その壱)

##キーワード
AssetBundle
アセット制作 texture \ mesh \ material \ Shader \ audio \ animation
Lightmap

---
##一、AssetBundle相関
**Q1: UnityのSerializedFileはどのように生成しましたか？ Unload（false）でクリアできますか？Bundleにある内容は読み込んだ後、他のオブジェクトに付値されました。そして、全ての画像をBundleにパッケージして読み込んだら、画像のサイズはこのSerializedFileのサイズを超えるはずでしょう？**
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/99c662eb-d88f-27d4-6f45-7ce1eaefb087.jpeg)
>SerializedFileは、AssetBundleがロード時に生成したシリアル化された情報です。通常、LoadFromCacheOrDownload、LoadFromFile、およびNewWWWがローカルAssetBundleファイルをロードすることによって発生します。AssetBundle内のアセットがすでにロードされていて、AssetBundleに依存するアセットがその後ロードされない場合は、Unload（false）でそれらを削除できます。SerializedFileに記録されているのは、含まれたアセットの内容ではなく、AssetBundleのシリアル化情報でありため、そのサイズは、リソースの実際のメモリよりも小さいか、はるかに小さくなります。

---
**Q2：今、2つのアセット管理方法を採用していますが、メモリ占用量の問題を理解したいです。
方式A：AssetBundleがロードされた後、メモリに保持されます。オブジェクトを作成する必要がある場合は、Instantiateによって作成します。
方法B：AssetBundleがロードされた後、すぐに一つのオブジェクトをインスタンスかして、このAssetBundleをUnload（false）します。必要な場合、cloneを介してオブジェクトを作成します。
方法Aの場合、関連するAssetBundleファイルがProfilerのWebStreamに存在し、このメモリは必要のないものと認めますから、方式Bを採用しましたが、方式Bはアセットのアンロードはクリーンではない状況に遭いました。一つ問題を確認したいのですが、方法Aを採用した場合：xxx.assetBundleの元のファイルサイズは1MBで、Webstreamメモリに解凍すると2MBになりますが、最終的に占用する実際のメモリは2MBまたは3MBですか？**
>方法Aを採用した場合：最終的な実際のメモリ使用量は3MBではなく2MBであり、WebStreamには元のAssetBundleのデータがすでに含まれています。依存関係のないAssetBundleファイルに対して、不要なメモリ占用を避けるために、方法BでAssetBundleをアンロードすることをお勧めします。この方法でロードされたアセットについては、Resources.UnloadAssetおよびResources.UnloadUnusedAssetsを使用してアンロードできます。アンロードできない場合は、このアセットは絶対キャッシュされています。開発チームが自分のバッファープール/Constainerをチェックして検出できます。同時に、Unity 5.3以降の場合は、MemoryProfilerでさらに確認することができます。

---
**Q3：パッケージ化中にAssetBundleのmd5は常に変更します（パッケージ化されているものは変更されていません）、どうすれば解決できますか？ある噂はDeterministicAssetBundleを追加したら大丈夫ですが、試したけどmd5は依然として変更します。**
>この方法は確かに役に立ちません。Unity 4.xバージョンのAssetBundleファイルに対して、確かにこのmd5値はある場合に前後不一致になります（パッケージ化されている内容は全く同じである場合でも）。このシリーズバージョンに対しては、開発チームに配置ファイルを生成してAssetBundleを管理することのみ提案できます。
但し、Unity 5.xバージョンの場合、パッケージ化時にAppendHashToAssetBundleNameオプションをオンにすることをお勧めします。これで、Unityエンジンは各AssetBundleファイルの後に唯一のHashIDを生成し（ファイル名の後に表示）、開発チームはこのIDで対応するAssetBundleファイルが変更されたかどうかを判断できます。

---
**Q4：NGUIなどの依存パッケージを使用する場合、アトラスAは依存されるパッケージとして使用され、インターフェイス1、2、3は独立パッケージとして別々に依存パッケージします。アトラスAを再パッケージ化する場合、インターフェイス1、2、3も再パッケージ化する必要がありますか？現在は、インターフェイスパッケージ化時にすべてのアトラス情報をクリアしてからパッケージ化し、クライアントにロードした後に動的に割り当て直します。これにより、アトラスを独立に更新できますが、ローディングパフォーマンスが犠牲になります。 より良い解決策はありますか？**
>「アトラスAを再パッケージ化する場合、インターフェイス1、2、3も再パッケージ化する必要がありますか？」これは必要ありません。Unity 4.xの依存関係パッケージの制限は、再パッケージ化するときに、依存する全てのパッケージを再パッケージ化する必要があることですが、それに依存せれるパッケージを再パッケージ化する必要はありません。

---
**Q5：内蔵Shaderのパッケージ化する方法は？内蔵シェーダーを使用しましたが、Shaderだけでなく、この時、下図のように、Profilerに見られるローディング結果は複数あります。**
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/07105efa-fc43-e196-983c-a8b91430e3a1.png)
>一般的に、二つ方法で内蔵Shaderをパッケージ化できます。
1、Graphics SettingsのAlways Included Shadersに添付します。この時、添付された内蔵ShaderはAssetBundleにバンドルさせません。
2、http://unity3d.com/cn/get-unity/download/archive で内蔵Shaderをダウンロードし、プロジェクトにインポートして、内蔵ではないシェーダーに置き換えます。そして、スクリプトからパッケージ化の方法を直接にコントロールできます。

---
**Q6：パーティクルエフェクトのシェーダーは依存関係パッケージを使用できませんか？シェーダーモデルと特殊効果に依存関係パッケージ化をしており、実行するとモデルの表示は正常ですが、パーティクル特殊効果が使用するシェーダーは正常に動作せず、特殊効果が異常に表示されます。エディターでは、Material中のShaderが存在していると確認できます。このとき、同じシェーダーを再度手動でマテリアルに割り当てると、パーティクルエフェクトが正常に表示されますが、原因は何ですか？**
>一部のShaderがAndroidバージョンのAssetbundleにパッケージされた後に、プラットフォームの非互換性のために正しく表示されません。これは、パッケージされた後のShaderコードはターゲットプラットフォームのプリコンパイルされたコードのみを保持し、Editorで実行できるかどうかもわかりませんから、これは正常です。しかし、実機でこのような問題は発生しないため、依存関係パッケージ化には影響しません。

---
**Q7：ResourceシーンにはScene1.unityとScene2.unityの2つのシーンがあります。 これらのファイルをパッケージ化したら、下記のようなファイルが取得できます。**

**Scene1.assetbundle
Scene1.assetbundle.meta
Scene2.assetbundle
Scene2.assetbundle.meta**

**同じアセットがある場合、理論的には2つのパッケージのそれぞれにコピーが保存されるため、パッケージ本体が大きくなりすぎます。したがって、各シーンが大きくなりすぎないために、共有アセットを依存対象として別々にパッケージ化する方法はありますか？**

>同じなアセットのAssetBundle名をしっかりと設定すれば、パッケージ化する時に自動的に抽出されます。

---
**Q8：現在、AssetBundleを生成すると、各ファイルに一つのManifestファイルが生成します。このファイルもAssetBundleと一緒にアップロードする必要がありますか？アセットがロードする時に具体的にどうせれば良いですか？**

>各ファイルによって生成されたManifestファイルをアップロードする必要はありません。その機能は、開発者がAssetBundle内の依存関係やその他の情報を確認できにさせることです。ただし、各ファイルが生成したManifest 以外に、ルートディレクトリの下にルートディレクトリと同じ名前のAssetBundleファイルとManifest ファイルもあります。実行時にこのAssetBundleをロードすると、AssetBundleManifestオブジェクトを取得でき、このオブジェクトからAssetBundleの直接依存関係を取得できます。

>これ以上の情報は、http://docs.unity3d.com/ScriptReference/AssetBundleManifest.html で参考してください。

---
**Q9：一つのPrefabがあります、そのDependenciesがResourcesフォルダーにある場合、AssetBundleをパッケージ化する時に、このPrefabのみをパッケージ化したら（BuildAssetBundleOptions.CompleteAssetsおよびBuildAssetBundleOptionsCollectDependenciesを指定しません）、このPrefabを正しくインスタンス化できますか？**

>AssetBundle内のアセットとResourceフォルダー内のアセットは依存関係を確立しないため、これを正しくインスタンス化することはできません（スクリプトを除き、BuildAssetBundleOptionsCollectDependenciesがオンになっている場合、スクリプトは依然としてAssetBundleにパッケージ化されません）。そのため、メッシュ、マテリアルなどが失われます。

---
**Q10：AssetBundleを介してShaderをプリロードした後、AssetBundleをアンロードしませんでしたが、後でロードされたObjectが正しくShaderに引用されていないことがわかりました。原因は何でしょうか。**

>プロジェクト内のAssetBundleの依存関係が正しくパッケージ化されていない可能性があります。後続のすべてのロードされたAssetBundleは、ShaderのAssetBundleファイルに依存する必要があります。これにより、Unityエンジンは後続のAssetBundleをロードするときにShaderを関連付けます。

---
**Q11：私のゲームには繰り返し特殊効果がたくさんあります。それらのいくつかは同じパターンですが、色のパラメーターが変更されています。それらをすべて独立AssetBundleにパッケージすると、メモリに複数のTextureがあります。そのようなパッケージには一般的に何が推奨案ありませんか？**

>内容が同じで全体の色のみが異なる場合は、プロジェクト内に初期テクスチャアセットのみを保留し、Shaderを介して実行中に全体的な色を変更し、さまざまな効果を実現することをお勧めします。但し、局部カラーが異なる場合、初期テクスチャに基づいて1つ又は1つ以上のMaskテクスチャを追加して、カラーの適応調整を行い、そしてShaderを介してさまざまな表示効果を実現できます。

---
**Q12：すみません。2つのプリセットに3番目のAssetBundleのテクスチャを引用していますが、このテクスチャが二枚存在したくない場合、必ずこの2つのプリセットがロードされた後に、テクスチャのAssetBundleをアンロードできませんか？**

>そうです。しかし、「このテクスチャが二枚存在したくない」という理由ではなく、テクスチャのAssetBundleを最初にアンインストールすると、後で2つのプリセットをロードしたときに依存関係を失われます、つまり、テクスチャが見つからなくなります。スクリプトでこの状況をチェックし、再びテクスチャのAssetBundleをロードすると、現時点に「このテクスチャが二枚存在」問題を導きます。

---
**Q13：下図の図1は、ゲームに入りばかり時に取得した情報で、図2は同じUIインターフェイスを数回切り替えた後に取得したものです。2つの画像を比較すると、重複するテクスチャが複数あることがわかりました。これはどうしてですか？ローディング方式はUIがAssetBundleを介してロードされ、ロード後にAssetBundleが解放されます。その後に再びUIをロードするとテクスチャアセットの冗長性が発生します。**
![6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/d21bb228-0e19-8ff3-d727-a08ff1518f8f.jpeg)
![7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/6a185820-b816-050b-8a9f-4274099262b9.jpeg)
>ゲームに入りばかり時に取得した、図にある「重複」アセットは冗長ではない可能性があります。Atlasの Groupにはサイズの同じPage（つまりテクスチャ）が複数含まれている可能性があり、これらのPageがメモリにある名前は同じです。

>ただし、同じUIインターフェイスを複数回開いた後、同じアセットがメモリにさらに出現する場合は、UI管理方法に特定の問題があることを示しています。頻繁に使用するUIに対して、ロード後にバッファプールを介してキャッシュし、後で使用する時にバッファプールを介して直接取得することをお勧めします。毎回AssetBundleを介してロードする必要はありません。この方法は、より高いCPU占用を導き、アセットの冗長性の可能性も高いです。

>同時に、複数回開かれたUIインターフェイスは異なる、メモリ内の同一種類のアセットの増加を導く場合、AssetBundleがパッケージ化されたときにUIが冗長性を生成する可能性は高いです（この状況は現在のUGUIシステムによく見られます）。これに対して、開発チームがUGUIを使用する場合、同じAtlas UIインターフェイスを可能な限りAssetBundleファイルにパックすることをお勧めします。そうしないと、リソースの冗長性が発生します。

---
**Q14：プロジェクトがリリースされたとき、Player Settingにチェックされたオプション（Optimize Mesh Data）は、パッケージ化されたおよびStreaming Assetsに配置されたAssetBundleファイルに効果ありませんか？ モデルアセットにOptimize Meshがありますが、同じ効果を達成できますか？**

>理論的には、Optimize Mesh DataはBuild Player 又はBundle 時にのみ有効になります。ですから、この前に作成したBundleは無効になさせます。さらに、2つのオプションの効果は異なります。後者は、パッチの順序を調整することです。

---
##二、アセットの使用
###テクスチャ相関
**Q1：ETC2形式の同じパッケージと同じアトラスがあり、Redmi Note1でのメモリはCoolpadでのメモリの4倍になります。これの原因は何ですか？ OpenGL 3.0をサポートしていない場合、このような大きな影響が発生しますか？**
>理論的に、ETC2形式はOpenGL ES 3.0デバイスでのみサポートされ、サポートされていないデバイスでは、内部でRGBA32 / ARGB32形式に自動的に変換されます。これは、RGBA Compressed ETC2 8bitsテクスチャの4倍です。 したがって、OpenGL ES 2.0デバイスで透明な素材を圧縮する場合は、Alphaチャネルを分離し、2つのETC1を使用して圧縮することができます。

---
**Q2：StreamingAssetsのテクスチャを動的にロードします。コードは次とおりです。**
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/57c03edc-c278-3e2a-eebe-f4a004fa8881.png)
**この方法のメモリコストは高いことがわかりました。一枚の512×512のテクスチャは2MBを占有します。公式の解析によると、メモリもビデオメモリも一部の占用が必要です。 テクスチャを動的にロードするための推奨される方法を知りたいですか？**
>一般的に、bytesストリームではなく、AssetBundleを介してアセットを動的にロードすることをお勧めします。 プロジェクトでこの方法を使用してテクスチャをロードしている場合は、戦略的に変更することを提案します。 現在から見ると、bytesストリームを介してアセットを生成する原因のほとんどは、アセットを解読しにくいように暗号化するためです。 しかし実際には、この暗号化方法はあまり役に立ちません。なぜなら、私たちの知る限り、Mali Graphics Debugger、Qualcomn Profilerなど、基盤となるグラフィックスレイヤーを介してさまざまなテクスチャやメッシュアセットを直接表示できるツールがたくさんあるからです。 したがって、暗号化の観点からbytesストリームを介してアセットを生成する場合は、AssetBundleの直接メソッドを介してロードすることをお勧めします。

---
**Q3：iOSプラットフォームでは、アトラスのRGBチャネルとAlphaチャネルを分離する必要がありますか？ 同じサイズの画像（正方形）で、RGB Compressed PVRTC 4bitsとRGBA Compressed PVRTC 4bitsの2つの形式が同じメモリを占用し、画像が2つに分割されている場合、iOSプラットフォームは2倍のメモリを占有ませんか ？ 透明なチャネルがある場合、そのアトラスをより適切に処理するにはどうすればよいですか？**

>iOSのPVRTC形式はAlphaチャネルをサポートしているため、通常、iOSではチャネル分離を行う必要はありません。ただし、iOSでのチャネル分離は歪みを減らし、視覚効果をある程度改善するのに役立つというチームからのフィードバックもあるため、比較を試みることもできます。

>占有されているメモリが同じであることが確認したら、元の画像はRGBです。 iOSでチャネル分離を行うと、メモリは確かに2倍になります。 UIテクスチャは、iOSでデフォルトのCompressを直接に選択でき、Atlasをパッケージする時にPVRTCに自動的に処理されます。開発チームは、Sprite packerウィンドウからAtlasの圧縮形式を確認できます。

---
**Q4：ゲームの特殊効果で使用されるテクスチャはたくさんありますが、それらを管理する良い方法はありますか？アトラスを合併しないと、何千枚の小さな透明テクスチャがあり、アトラスを合併するとメモリコストは高すぎです。**

>アトラスに合併することができます。一般的に、頻繁に同時出現するテクスチャは、過剰なメモリを発生させないように、可能な限りアトラスに合成されます。 これについて、前に推奨したプラグイン[Mesh Baker](https://qiita.com/UWATechnology/items/ff83181274a1ad151369)を参照することはできます。

---
**Q5: Texture Atlasは、一枚の2048（サイズ）テクスチャまたは四枚の1024テクスチャに合成することをお勧めしますか？**

>他の設定が同じ場合、実際には、ロードとレンダリングに関して2つの方法の間に実質的な違いはありません。 ほとんどの場合、テクスチャアセットのサイズ以外に、テクスチャフォーマット、Mipmap設定、およびRead&Write機能にも、開発チームが注意する必要があります。

---
**Q6: NGUIアトラスはメモリにたくさんありますが、どうすればクリーンアップできますか？**
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/30940a6d-69f5-9fb7-bba3-2941d05ddcae.png)
>ゲーム実行中に、UI Meshが異なるメモリに存在することは正常です。UI widgetの使用が増減および減少すると、作成されるUI Meshが変化します。同時に、異なるUIPanelに同じAtlasのWidgetsが存在すれば、上記のような状況も出現できます。したがって、このような状況に遭う場合には、単一フレームに同じ名前のNGUI UI Meshを持つアセットが複数あるかどうかを確認することをお勧めします。存在する場合は、同じAtlas内のアセットが複数の異なるUIPanelによって使用されていることを意味します。この状況は、可能な限り回避する必要があります。

---
**Q7: UWAレポートに多数のn / aアセットが見られます。フォーマットの高さと幅が取得できず、繰り返しが多くあります。これらのファイルをどうやって定位すれば良いですか？最適化して解決できますか？**

>n/aアセットは私たちがプロジェクト実行中に検出された名前の無いアセットです。一般的に、このタイプのアセットはAssetフォルダー内のアートアセットではなく、プロジェクトがスクリプトを介して動的に生成されたアセットです。例えば、new Mesh、new Textureなどの操作で、このような名前の無いアセットを生成しやすいです。

>これに対して、開発チームにロジックコード/サードパーティのプラグインにあるNew Mesh/Textureなどの操作を詳しく検査することをお勧めします。同時に、プラグインがこのようなアセットを動的に生成した後に、名前をつけることも推薦します。そして、後続のテストで名前の対するアセットの使用状況を確認できます。

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

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