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