Version: 2020.3
에셋 번들 빌드
에셋 번들의 전문적인 활용

에셋 번들 종속성

에셋 번들에 속한 UnityEngine.Objects 중 하나 이상이 다른 번들에 있는 UnityEngine.Object에 대한 레퍼런스를 가지고 있을 경우 해당 에셋 번들은 다른 에셋 번들에 종속합니다. 하지만, 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.

에셋 번들 빌드
에셋 번들의 전문적인 활용