Version: 5.4
에셋 번들에서 오브젝트 로드 및 언로드(Loading and unloading objects from an AssetBundle)
에셋 번들에 바이너리 데이터 저장 및 로드

로드된 에셋 번들(AssetBundles) 추적(Track)

Unity에서는 특정 에셋 번들의 인스턴스를 한 번에 하나씩만 애플리케이션에 로드할 수 있습니다. 즉, 이전에 로드된 후 언로드되지 않은 에셋 번들을 WWW 오브젝트에서 검색해서 가져올 수 없습니다. 실제 예를 들어서 설명하면, 다음과 같이 이전에 로드된 에셋 번들에 액세스하려고 할 경우

 AssetBundle bundle = www.assetBundle;

다음 오류가 발생하고

 Cannot load cached AssetBundle. A file of the same name is already loaded from another AssetBundle

에셋 번들 프로퍼티가 null을 반환합니다. 첫 번째 에셋 번들이 아직 로드되어 있는 경우 두 번째 다운로드 중에 에셋 번들을 검색해서 가져올 수 없으므로, 에셋 번들을 더 이상 사용하지 않을 때 언로드_하거나, 에셋 번들이 이미 메모리에 있는 경우 번들에 대한 레퍼런스를 유지하고 가급적 다운로드하지 않아야 합니다. 필요에 따라 적절한 방법을 결정할 수 있지만, 오브젝트가 전부 로드된 후 에셋 번들을 즉시 언로드_하는 것이 좋습니다. 그러면 메모리를 다시 사용할 수 있게 되고 캐싱된 에셋 번들을 로드하는 것과 관련된 오류가 더 이상 발생하지 않습니다.

Unity 5보다 오래된 버전에서는 모든 번들의 로딩이 완료된 후에만 번들이 언로드되었습니다. 따라서 일부 번들이 아직 로드 중일 때 AssetBundle.Unload 함수를 호출하면 모든 번들이 로드될 때까지 나머지 코드의 실행이 차단되었습니다. 이로 인해 성능 문제가 가중되었습니다. 이 문제는 Unity 5에서 수정되었습니다.

다운로드한 에셋 번들을 추적하려는 경우, 래퍼 클래스를 사용하여 다음과 같이 다운로드를 관리할 수 있습니다.

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;

static public class AssetBundleManager {
   // A dictionary to hold the AssetBundle references
   static private Dictionary<string, AssetBundleRef> dictAssetBundleRefs;
   static AssetBundleManager (){
       dictAssetBundleRefs = new Dictionary<string, AssetBundleRef>();
   }
   // Class with the AssetBundle reference, url and version
   private class AssetBundleRef {
       public AssetBundle assetBundle = null;
       public int version;
       public string url;
       public AssetBundleRef(string strUrlIn, int intVersionIn) {
           url = strUrlIn;
           version = intVersionIn;
       }
   };
   // Get an AssetBundle
   public static AssetBundle getAssetBundle (string url, int version){
       string keyName = url + version.ToString();
       AssetBundleRef abRef;
       if (dictAssetBundleRefs.TryGetValue(keyName, out abRef))
           return abRef.assetBundle;
       else
           return null;
   }
   // Download an AssetBundle
   public static IEnumerator downloadAssetBundle (string url, int version){
       string keyName = url + version.ToString();
       if (dictAssetBundleRefs.ContainsKey(keyName))
           yield return null;
       else {
           while (!Caching.ready)
               yield return null;

           using(WWW www = WWW.LoadFromCacheOrDownload (url, version)){
               yield return www;
               if (www.error != null)
                   throw new Exception("WWW download:" + www.error);
               AssetBundleRef abRef = new AssetBundleRef (url, version);
               abRef.assetBundle = www.assetBundle;
               dictAssetBundleRefs.Add (keyName, abRef);
           }
       }
   }
   // Unload an AssetBundle
   public static void Unload (string url, int version, bool allObjects){
       string keyName = url + version.ToString();
       AssetBundleRef abRef;
       if (dictAssetBundleRefs.TryGetValue(keyName, out abRef)){
           abRef.assetBundle.Unload (allObjects);
           abRef.assetBundle = null;
           dictAssetBundleRefs.Remove(keyName);
       }
   }
}

클래스의 사용 예제는 다음과 같습니다.

using UnityEditor;

class ManagedAssetBundleExample : MonoBehaviour {
   public string url;
   public int version;
   AssetBundle bundle;
   void OnGUI (){
       if (GUILayout.Label ("Download bundle"){
           bundle = AssetBundleManager.getAssetBundle (url, version);
           if(!bundle)
               StartCoroutine (DownloadAB());
       }
   }
   IEnumerator DownloadAB (){
       yield return StartCoroutine(AssetBundleManager.downloadAssetBundle (url, version));
       bundle = AssetBundleManager.getAssetBundle (url, version);
   }
   void OnDisable (){
       AssetBundleManager.Unload (url, version);
   }
}

예제에서 AssetBundleManager 클래스는 정적이고, 사용자가 레퍼런스하는 에셋 번들은 새 씬을 로드할 때 소멸되지 않습니다. 클래스를 참고하되, 권장 방법에 따라 처음에는 에셋 번들을 사용한 후 곧바로 _언로드_하는 것이 가장 효과적입니다. 이전에 인스턴스화한 오브젝트를 언제든지 복제하여 에셋 번들을 다시 로드해야 하는 필요성을 없앨 수 있습니다.

에셋 번들에서 오브젝트 로드 및 언로드(Loading and unloading objects from an AssetBundle)
에셋 번들에 바이너리 데이터 저장 및 로드