에셋 번들의 디스크 검색 최적화(Optimizing disk seeks with AssetBundles)
빌드 파일 크기 축소

에셋 번들 자주 묻는 질문(AssetBundles FAQ)

에셋 번들을 어떻게 사용합니까?

에셋 번들을 작업할 때 크게 두 가지 단계가 있습니다. 첫 번째는 서버나 디스크 위치에서 에셋 번들을 다운로드 하는 것으로, WWW 클래스에서 실시합니다. 두 번째는 응용 프로그램에서 사용할 에셋 번들에서 에셋을 로드하는 단계입니다. 다음은 C# 스크립트의 예제입니다.

using UnityEngine;
using System.Collections;

public class BundleLoader : MonoBehaviour{
    public string url;
    public int version;
    public IEnumerator LoadBundle(){
        while (!Caching.ready)
            yield return null;
        using(WWW www = WWW.LoadFromCacheOrDownload(url, version)) {
            yield return www;
            AssetBundle assetBundle = www.assetBundle;
            GameObject gameObject = assetBundle.mainAsset as GameObject;
            Instantiate(gameObject);
            assetBundle.Unload(false);
        }
    }
    void Start(){
        StartCoroutine(LoadBundle());
    }
}

이 스크립트는 게임 오브젝트에 컴포넌트로 추가된 것입니다. 에셋 번들은 다음과 같은 방법으로 로드됩니다.

  • 이 스크립트를 실행하기 전에 인스펙터에서 url 및 버전 값을 설정해야 합니다. url은 에셋 번들 파일의 위치로, 일반적으로 인터넷상의 서버입니다. 버전의 번호는 디스크의 캐시에 기록될 때 개발자가 에셋 번들에 숫자를 지정하도록 해줍니다. 에셋 번들을 다운로드할 때 Unity는 캐시에 이미 파일이 존재하는지 확인합니다. 만약 존재한다면 저장된 에셋과 요청된 버전을 비교합니다. 일치하지 않으면 에셋 번들을 다시 다운로드하고, 일치하면 디스크에서 에셋 번들을 로드해 파일을 다시 다운로드하지 않습니다. 이런 파라미터와 관련한 보다 자세한 내용은 스크립팅 레퍼런스의 WWW.LoadFromCacheOrDownload 함수를 참조하십시오.
  • 이 스크립트의 Start 함수가 호출되면 코루틴으로 함수를 호출해 AssetBundle 로드를 시작합니다. 이 함수는 에셋 번들을 다운로드 하면서 WWW 오브젝트를 넘겨줍니다. 이것을 사용하면 이 함수는 WWW 오브젝트의 다운로드가 완료될 때까지 그 지점에서 멈춰있지만 나머지 코드의 실행을 차단하지 않고 완료될 때까지 반복합니다. WWW.LoadFromCacheOrDownload로 다운로드할 때 프레임당 하나의 AssetBundle만 다운로드 완료될 수 있습니다.
  • WWW 오브젝트가 에셋 번들 파일을 다운로드하면 .assetBundle 프로퍼티를 사용해 에셋 번들 오브젝트를 조회합니다. 이 오브젝트는 에셋 번들 파일에서 오브젝트를 로드하는 인터페이스입니다.
  • 위의 예에서는 에셋 번들에서 프리팹의 참조가 .mainAsset 프로퍼티를 사용해 조회되었습니다. 이 프로퍼티는 오브젝트를 첫 번째 파라미터로 전달하여 에셋 번들을 빌드할 때 설정됩니다. 에셋 번들의 메인 에셋은 에셋 번들 안에 오브젝트 리스트 및 다른 기타 정보를 가지고 있는 TextAsset을 저장하는 데 활용될 수 있습니다.

간단한 설명을 위해 이번 예에서는 안정성 검사를 전혀 하지 않았습니다. 보다 온전한 예는 여기에서 확인합니다.

어떻게 에디터에서 에셋 번들을 사용합니까?

애플리케이션을 만드는 것은 반복적인 프로세스이기 때문에 에셋을 여러 번 수정할 가능성이 높습니다. 또 변경사항이 있을 때마다 에셋 번들을 테스트할 수 있도록 다시 빌드해야 합니다. 에디터에서 에셋 번들을 로드할 수는 있지만 권장하는 방식은 아닙니다. 대신 에디터에서 테스트할 때 에셋 번들의 사용과 재빌드를 피하기 위해 헬퍼 함수 Resources.LoadAssetAtPath를 사용해야 합니다. 이 함수는 에셋이 에셋 번들에서 로드한 것처럼 해주지만 빌드 프로세스를 건너뛰고 에셋은 항상 최신의 상태로 유지됩니다.

다음은 헬퍼 스크립트의 예제로, 에디터에서 실행하느냐 아니냐에 따라 에셋을 로드하는 데 사용할 수 있습니다. 이 코드를 AssetBundleLoader.cs라는 C# 스크립트에 넣습니다.

using UnityEngine;
using System.Collections;

public class AssetBundleLoader {
    public Object Obj; // The object retrieved from the AssetBundle
   
    public IEnumerator LoadBundle<T> (string url, int version, string assetName, string assetPath) where T : Object {
        Obj = null;

#if UNITY_EDITOR
        Obj = Resources.LoadAssetAtPath(assetPath, typeof(T));
        if (Obj == null)
            Debug.LogError ("Asset not found at path: " + assetPath);
        yield break;

#else

        WWW download;
        if ( Caching.enabled ) { 
            while (!Caching.ready)
                yield return null;
           download = WWW.LoadFromCacheOrDownload( url, version );
        }
        else {
            download = new WWW (url);
        }

        yield return download;
        if ( download.error != null ) {
            Debug.LogError( download.error );
            download.Dispose();
            yield break;
        }

        AssetBundle assetBundle = download.assetBundle;
        download.Dispose();
        download = null;

        if (assetName == "" || assetName == null)
        Obj = assetBundle.mainAsset;
        else
            Obj = assetBundle.Load(assetName, typeof(T));
       
        assetBundle.Unload(false);

#endif
    }
}

이제 이 AssetBundleLoader 스크립트를 사용하면, 빌드한 애플리케이션을 실행하는 경우 에셋 번들에서 에셋을 로드하고, 에디터를 실행할 때는 프로젝트 폴더에서 에셋을 직접 로드할 수 있습니다.

using UnityEngine;
using System.Collections;

public class ExampleLoadingBundle : MonoBehaviour {
    public string url = "http://www.mygame.com/myBundle.unity3d"; // URL where the AssetBundle is
    public int version = 1; // The version of the AssetBundle

    public string assetName = "MyPrefab"; // Name of the Asset to be loaded from the AssetBundle
    public string assetPath; // Path to the Asset in the Project folder

    private Object ObjInstance; // Instance of the object
    void Start(){
        StartCoroutine(Download());
    }

    IEnumerator Download () {
        AssetBundleLoader assetBundleLoader = new AssetBundleLoader ();
        yield return StartCoroutine(assetBundleLoader.LoadBundle <GameObject> (url, version, assetName, assetPath));
        if (assetBundleLoader.Obj != null)
            ObjInstance = Instantiate (assetBundleLoader.Obj);
    }

    void OnGUI(){
        GUILayout.Label (ObjInstance ? ObjInstance.name + " instantiated" : "");
    }
}

앞의 스크립트를 Assets 폴더의 ExampleLoadingBundle.cs 파일에 저장해야 합니다. public 변수를 올바른 값으로 설정하고 실행하면 에셋을 로드하는 데 AssetBundleLoader 클래스를 사용합니다. 그 후에는 인스턴스화 되고 GUI를 사용해 표시합니다.

에셋 번들을 어떻게 캐시합니까?

WWW.LoadFromCacheOrDownload를 사용해 에셋 번들을 자동으로 디스크에 저장할 수 있습니다. 추가로 공간이 필요한 경우 별도로 캐싱 라이선스를 구입할 수 있습니다.

에셋 번들이 StreamingAssets 폴더에 압축되지 않은 에셋 번들로 저장되어 있으면 디스크의 에셋 번들을 참조하는 데 AssetBundle.CreateFromFile을 사용할 수 있습니다. StreamingAssets 폴더의 에셋 번들이 압축되어 있으면 캐시에 있는 에셋 번들의 압축되지 않은 복사본을 생성하기 위해 WWW.LoadFromCacheOrDownload를 사용해야 합니다.

에셋 번들은 크로스 플랫폼입니까?

일부 플랫폼에서 에셋 번들이 호환됩니다. 다음 표를 가이드라인으로 활용하세요.

플랫폼 간 에셋 번들 호환성
스탠드얼론 iOS Android
에디터 Y Y* Y*
스탠드얼론 Y
iOS Y
Android Y

(*)모바일 플랫폼용으로 빌드된 에셋 번들은 에디터가 실행되고 있는 플랫폼과 호환되지 않는 특정 플랫폼에 최적화된 포맷으로 저장된 데이터를 포함할 수도 있습니다. 발매된 게임에는 플랫폼마다 서로 다른 에셋 번들이 필요하다고 가정하는 편이 안전합니다. 특히 셰이더는 플랫폼마다 다릅니다.

E.g. GI data is stored in a format optimized for ARM architecture and thus is not loadable on x86 CPUs. Shaders are stored for OpenGLES 2 configuration and are not loadable by the Editor which uses the DX9/11 renderer (but works with OpenGLCore renderer). During development, you are recommended to use Simulation Mode mentioned in AssetBundles and the AssetBundle Manager tutorial to avoid Editor and mobile platforms incompatibility.

에셋 번들의 에셋은 어떻게 확인합니까?

에셋 번들을 빌드할 때 내부적으로는 확장자를 제외한 파일 이름으로 에셋을 식별합니다. 예를 들어, Project 폴더의 ​​“Assets/Textures/myTexture.jpg”에 위치한 텍스처는 기본 메서드를 사용할 경우 “myTexture”로 확인 및 로드됩니다. 에셋 번들을 BuildPipeline.BuildAssetBundleExplicitAssetNames를 이용해 빌드하면 오브젝트별로 자체적인 ID(문자열) 배열을 제공하여 이보다 더 많은 제어를 할 수 있습니다.

에셋 번들을 다른 게임에서도 재사용할 수 있습니까?

에셋 번들은 서로 다른 게임 간에 콘텐츠를 공유하게 해줍니다. 그러려면 에셋 번들의 게임 오브젝트로 참조되는 모든 에셋이 에셋 번들에 포함돼야 합니다. 참조된 에셋이 빌드되었을 때 에셋 번들에 확실하게 포함되게 하려면 BuildAssetBundleOptions.CollectDependencies 옵션을 전달하면 됩니다.

현재 빌드한 에셋 번들을 Unity의 이후 버전에서도 사용할 수 있습니까?

에셋 번들은 에셋 타입에 대한 정보를 다른 버전의 Unity에서도 이해할 수 있게 만드는 __타입 트리__라는 구조를 포함할 수 있습니다. 타입 트리는 거의 모든 플랫폼에서 기본적으로 포함되지만, BuildAssetBundleOptions.DisableWriteTypeTreeBuildAssetBundle 함수에 전달해서 비활성화할 수 있습니다.

타입 트리는 Windows Store/유니버설 Windows 플랫폼을 타겟으로 .NET 스크립팅 백엔드를 사용할 때는 지원되지 않으므로, 이런 번들은 직렬화 포맷이 바뀔 때마다 다시 빌드해야 합니다. 이는 새로운 버전의 Unity에서 발생할 수 있습니다. 에셋 번들에 포함된 MonoBehaviour에 직렬화된 필드를 추가하거나 삭제할 때도 발생할 수 있습니다. 에셋 번들을 로드하려고 할 때 에셋 번들을 다시 빌드해야 한다면 Unity가 오류 메시지를 출력합니다.

에셋 번들에서 오브젝트 리스트를 어떻게 얻을 수 있습니까?

에셋 번들에서 모든 오브젝트를 포함하는 배열을 조회하는 데 AssetBundle.LoadAllAssets를 활용할 수 있습니다. 그러나 식별자 리스트를 직접 얻을 수는 없습니다. 일반적인 해결책은 에셋 번들에 있는 에셋들의 이름을 갖고 있는 별도의 TextAsset을 두는 것입니다.

에셋 번들은 어떻게 다른 에셋 번들의 에셋을 참조합니까?

번들 A가 머티리얼과 텍스처를 가진 프리팹을 포함한다고 가정해보겠습니다. 번들 B에는 동일한 프리팹의 인스턴스를 가진 씬이 있습니다. 번들B는 해당 머티리얼에 액세스해야 합니다. 이 머티리얼이 특정 에셋 번들에 포함되지 않으면 A와 B 번들 모두에 포함됩니다.

에셋 번들의 디스크 검색 최적화(Optimizing disk seeks with AssetBundles)
빌드 파일 크기 축소