最終更新:
bokkuri_orz 2015年02月18日(水) 01:44:50履歴
複数のアセットバンドルをビルドする時、それぞれに含まれるオブジェクトが共通のマテリアルを参照していても、
個々のアセットバンドルに別物として含まれてしまいます。
実際にアプリ内でそれらのアセットバンドルをロードし、個々のオブジェクトをロードすると、
先ほどの共通のマテリアルが重複してメモリ上に乗ります。
●アセット ・material_A ・object_A … material_A を参照 ・object_B … material_A を参照 ●アセットバンドル ・AssetBundle_A … material_A object_A ・AssetBundle_B … material_A object_B ↓ アセットバンドルを読み込んで、object_A, object_B をロードする ●メモリ ・AssetBundle_A からロード ・object_A ・material_A ・AssetBundle_B からロード ・object_B ・material_A' … 共通のマテリアルだったはずが、メモリ上に別物としてロードされる
UnityProfilerで見ると、マテリアルが2個増えることが確認できます。
Resources.FindObjectsOfTypeAll(typeof(Material)) でも確認できます。
※この問題を解決するために、アセットバンドルの依存関係を指定してビルドします。
Object[] m_commonRes; // 共通リソース。共有アセットバンドルとしてビルドする。
Object[] m_objects; // 共通リソースに依存するオブジェクト。
private void BuildAssetBundle()
{
BuildTarget platform; //プラットフォームはどこかから取得
BuildAssetBundleOptions option =
BuildAssetBundleOptions.CollectDependencies |
BuildAssetBundleOptions.CompleteAssets |
BuildAssetBundleOptions.DeterministicAssetBundle; //※必須オプション。後で一部のアセットバンドルを再ビルドする際、オブジェクトの識別に利用される。
// 毎回全てのアセットバンドルをビルドし直すのであれば、このオプションは不要と思われる。
// 共有アセットバンドルの依存関係開始
BuildPipeline.PushAssetDependencies();
// 共有アセットバンドルをビルド
BuildPipeline.BuildAssetBundle(null, m_commonRes, "common.unity3d", option, platform);
for(int i = 0; i < m_objects.Length; ++i)
{
// 個別のアセットバンドルもPush, Pop で囲む
BuildPipeline.PushAssetDependencies();
// 個別のアセットバンドルをビルド
// ※ここで共有アセットバンドルに含まれるリソースは、このアセットバンドルには含まれない。
BuildPipeline.BuildAssetBundle(m_objects[i], new Object[]{m_objects[i]}, m_objects[i].name + ".unity3d", option, platform);
BuildPipeline.PopAssetDependencies();
}
// 共有アセットバンドルの依存関係終了
BuildPipeline.PopAssetDependencies();
}
※注意点
共有アセットバンドルの参照を保持した状態でそれに依存するアセットバンドルをロードすると、リソースを正しく参照できる。
AssetBundle m_commonAB;
Object[] m_commonObj;
Object m_objA;
Object m_objB;
IEnumerator Download()
{
// 共有アセットバンドルの読み込み.
WWW loader = WWW.LoadFromCacheOrDownload("common.unity3d", 0);
while(!loader.isDone) yield return new WaitForSeconds(0.1f);
// 共有アセットバンドル取得後、LoadAll()で一旦全てロードすることで、リソースがメモリ上に乗る。
// アセットバンドルはUnload()せずに保持し続ける。
commonAB = loader.assetBundle;
m_commonObj = commonAB.LoadAll();
//---- 依存しているアセットバンドル
// AssetBundleA
loader = WWW.LoadFromCacheOrDownload("AssetBundleA.unity3d", 0);
while(!loader.isDone) yield return new WaitForSeconds(0.1f);
// 必要なオブジェクトをロードして、アセットバンドルは即解放.
AssetBundle ab = loader.assetBundle;
m_objA = ab.Load("objectA", typeof(GameObject));
ab.Unload(false);
// AssetBundleB
loader = WWW.LoadFromCacheOrDownload("AssetBundleB.unity3d", 0);
while(!loader.isDone) yield return new WaitForSeconds(0.1f);
ab = loader.assetBundle;
m_objB = ab.Load("objectB", typeof(GameObject));
ab.Unload(false);
}
Unity公式:アセット依存関係の管理 / Managing asset dependencies
http://docs-jp.unity3d.com/Documentation/Manual/ma...
keijiroさん:アセットバンドルとシェーダー
https://github.com/keijiro/unity-shader-bundle
タグ


最新コメント