アセットバンドルは、他のバンドル内にある UnityEngine.Object への参照を含む UnityEngine.Objects がひとつでもあると、他のアセットバンドルに依存する可能性があります。この依存は、UnityEngine.Object の参照先の UnityEngine.Object がどのアセットバンドルにも含まれていない場合には発生しません。この場合は、アセットバンドルのビルド時に、そのバンドルの依存先オブジェクトのコピーが同バンドル内にコピーされます。複数のバンドル内の複数のオブジェクトが、どのバンドルにも割り当てられていない同一オブジェクトへの参照を含んでいる場合、そのオブジェクトに依存する各バンドルがそれぞれにそのオブジェクトのコピーを作成し、作成されたアセットバンドルに加えます。
アセットバンドルに依存関係がある場合は、インスタンス化しようとしているオブジェクトより先にそのアセットバンドルをロードすることが重要です。Unity は自動的には依存関係をロードしません。
以下の例を参照してください。Bundle 1 にあるマテリアルが Bundle 2 のテクスチャを参照しています。
この例では、Bundle 1 からマテリアルをロードする前に、Bundle 2 をメモリにロードする必要があります。Bundle 1 と Bundle 2 をロードする順序はどちらが先でも問題ありません。重要なのは、Bundle 1 からマテリアルをロードする前に Bundle 2 をロードすることです。アセットバンドルを使いこなすのセクションでは、ビルドによって生成された AssetBundleManifest オブジェクトを使用して、ランタイムに依存関係の定義とロードを行う方法を説明しています。
デフォルトでは、Unity はアセットバンドル間で重複する情報をうまく利用できません。つまり、プロジェクト内の複数のアセットバンドルに、複数のプレハブで使用されるマテリアルなど、同じ情報が含まれる場合があります。複数のアセットバンドルで使用されるアセットは共通アセットと呼ばれます。これらはメモリリソースとロード時間に影響する場合があります。
このページでは、Unity がアセットバンドルで重複した情報を管理する方法と、最適化する方法について説明します。
###エディターの設定
デフォルトでは、Unity は重複情報の保存に必要なメモリを削減または最小にするための最適化を実行しません。ビルドの作成中に、Unity はアセットバンドル内の暗示的に参照されるアセットの複製をビルドします。デフォルトでは、Unity は重複情報の保存に必要なメモリを削減または最小にするための最適化を実行しません。ビルドの作成中に、Unity はアセットバンドル内の暗示的に参照されるアセットの複製をビルドします。この重複を防ぐには、共通のアセット (マテリアルなど) を独自のアセットバンドルに指定します。
例えば、2 つのプレハブを持つアプリケーションがあり、その両方が独自のアセットバンドルに割り当てられているとします。プレハブはどちらも、アセットバンドルに割り当てられていない同じマテリアルを共有しています。このマテリアルはアセットバンドルに割り当てられていないテクスチャを参照します。
アセットバンドルのワークフロー に従い、サンプルのクラス CreateAssetBundles を使用してアセットバンドルをビルドすると、生成された各アセットバンドルにはマテリアル (シェーダーと参照されるテクスチャを含む) が追加されます。下の画像の例では、プレハブファイルのサイズはそれぞれ 383 KB と 377 KB です。
プロジェクトに含まれるプレハブの数が多い場合、両方のアセットバンドルをロードすると、この動作はインストーラーの最終的なサイズと、ランタイムのメモリフットプリントに影響します。Unity は同じマテリアルの各コピーを一意のマテリアルとみなすため、アセットバンドル間のデータの重複はバッチ処理にも影響します。
データの重複を避けるには、マテリアルとその参照アセットを独自の modulesmaterials アセットバンドルに割り当てます。マテリアルのみにタグを付けることもできます。これは、テクスチャの依存関係もビルドプロセス中に自動的にアセットバンドルに追加されるためです。
これで、アセットバンドルをリビルドすると、生成された出力に別の modulesmaterials アセットバンドル (359 KB) が追加され、これにはマテリアルとそれに関連するテクスチャが含まれます。これにより、プレハブの他のアセットバンドルのサイズが大幅に削減されます (前のイテレーションの約 380 KB から約 20 KB に減少)。
下の画像はこれを示しています。
###ランタイムのロード
共通のアセットを 1 つのアセットバンドルに抽出する場合は、依存関係に注意してください。特に、モジュールのインスタンス化にプレハブのみを使用する場合、マテリアルはロードされません。
この問題を解決するには、モジュールに属するアセットバンドルをロードする前に、マテリアルのアセットバンドルをメモリにロードします。以下の例では、これは変数 materialsAB に発生します 。
using System.IO;
using UnityEngine;
public class InstantiateAssetBundles : MonoBehaviour
{
void Start()
{
var materialsAB = AssetBundle.LoadFromFile(Path.Combine(Application.dataPath, Path.Combine("AssetBundles", "modulesmaterials")));
var moduleAB = AssetBundle.LoadFromFile(Path.Combine(Application.dataPath, Path.Combine("AssetBundles", "example-prefab")));
if (materialsAB == null || moduleAB == null)
{
Debug.Log("Failed to load AssetBundle!");
return;
}
var prefab = moduleAB.LoadAsset<GameObject>("example-prefab");
Instantiate(prefab);
}
}
注意LZ4 圧縮と非圧縮のアセットバンドルを使用する場合、AssetBundle.LoadFromFile はそのコンテンツのカタログをメモリにのみロードし、コンテンツ自体はロードしません。これが発生しているかどうかを確認するには、Memory Profiler パッケージを使用してメモリ使用量を確認します。