Version: 2019.4
アセットバンドルのビルド
アセットバンドルを使いこなす

アセットバンドルの依存性

AssetBundle (アセットバンドル) は、他のバンドル内に UnityEngine.Object への参照がひとつでもあると、他のアセットバンドルに依存する可能性があります。この依存は、参照先の UnityEngine.Object がどのアセットバンドルにも含まれていない場合には発生しません。この場合は、アセットバンドルのビルド時に、そのバンドルの依存先オブジェクトが同バンドル内にコピーされます。複数のバンドル内のオブジェクトが、どのバンドルにも割り当てられていない同一オブジェクトへの参照を含んでいる場合、そのオブジェクトに依存する各バンドルそれぞれにそのオブジェクトが、作成されたアセットバンドル内にコピーされます。

アセットバンドルに依存が含まれる場合は、インスタンス化しようとしているオブジェクトより先にそのアセットバンドルを読み込むことが重要です。 Unity は自動的には依存関係を読み込みません。

例えば、バンドル1 にあるマテリアルが バンドル2 のテクスチャを参照している場合を考えてみてください。

この例では、 バンドル1 からマテリアルを読み込む前に、 バンドル2 をメモリに読み込む必要があります。 バンドル1バンドル2 を読み込む順序はどちらが先でも問題ありません。重要なのは バンドル1 からマテリアルを読み込む前に バンドル2 を読み込むということです。次の項では、前の項で触れた AssetBundleManifest オブジェクトを使用して、ランタイムで依存の定義および読み込みを行う方法を説明します。

Duplicated information across AssetBundles

By default, Unity doesn’t optimize duplicated information across AssetBundles. This means multiple AssetBundles in your Project might contain the same information, such as a Material which is used by multiple Prefabs. Assets which are used in multiple AssetBundles are known as common Assets. These can affect memory resources and loading times.

This page describes how Unity manages duplicated information across AssetBundles, and how you can apply optimization.

Editor setup

By default, Unity doesn’t perform any optimization to reduce or minimize the memory required to store duplicate information. During build creation, Unity builds duplicates of any implicitly referenced Assets inside the AssetBundles. To prevent this duplication, assign common Assets (such as Materials) to their own AssetBundle.

For example: you could have an application with two Prefabs, both of which are assigned to their own AssetBundle. Both Prefabs share the same Material, which is not assigned to an AssetBundle. This Material references a Texture, which is not assigned to an AssetBundle.

If you follow the AssetBundle Workflow and use the example class CreateAssetBundles to build AssetBundles, each generated AssetBundle contains the Material (including its Shader and referenced Textures). In the example image below, the Prefab files have a size of 383 KB and 377 KB respectively.

If the project contains a larger number of Prefabs, this behaviour impacts the final installer size, and the runtime memory footprint when both AssetBundles are loaded. Data duplication across AssetBundles also impacts batching, because Unity considers each copy of the same Material as a unique Material.

To avoid data duplication, assign the Material and its referenced Assets to its own modulesmaterials AssetBundle. You can also tag the Material only, because the Texture dependency is also included in the AssetBundle automatically during the build process.

Now if you rebuild the AssetBundles, the generated output includes a separate modulesmaterials AssetBundle (359 KB), which contains the Material and its associated Texture. This significantly reduces the size of the other AssetBundles for the Prefabs (from roughly 380 KB in the previous iteration down to roughly 20 KB).

The image below illustrates this.

Runtime loading

When you extract common Assets to a single AssetBundle, be careful about dependencies. In particular, if you only use a Prefab to instantiate a module, the Materials do not load.

A Prefab without a loaded Material
A Prefab without a loaded Material

To solve this problem, load the Materials AssetBundle in memory before you load the AssetBundle that belongs to the module. In the following example, this happens in the variable 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);
    }
}

A Prefab with a correctly loaded Material
A Prefab with a correctly loaded Material

Note: When you use LZ4 compressed and uncompressed AssetBundles, AssetBundle.LoadFromFile only loads the catalog of its content in memory, but not the content itself. To check if this is happening, use the Memory Profiler package to inspect memory usage.

アセットバンドルのビルド
アセットバンドルを使いこなす