Version: 5.4
Загрузка и выгрузка объектов из AssetBundle
Сохранение и загрузка бинарных данных в AssetBundle

Отслеживание загружаемых пакетов ассетов (AssetBundles)

Unity позволит одновременно загружать в ваше приложение только один экземпляр пакета ассетов (AssetBundle). Это означает только то, что вы не сможете восстановить пакет ассетов (AssetBundle) из WWW объекта, если ранее был загружен точно такой же пакет, но при этом не был выгружен. На практике это означает что, когда вы пытаетесь получить доступ к ранее загруженному пакету ассетов (AssetBundle) следующим образом:

 AssetBundle bundle = www.assetBundle;

будет выдана следующая ошибка

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

and the assetBundle property will return null. Since you can’t retrieve the AssetBundle during the second download if the first one is still loaded, what you need to do is to either unload the AssetBundle when you are no longer using it, or maintain a reference to it and avoid downloading it if it is already in memory. You can decide the right course of action based on your needs, but our recommendation is that you unload the AssetBundle as soon as you are done loading objects. This will free the memory and you will no longer get an error about loading cached AssetBundles.

Please note that before Unity 5 all bundles would finish loading before any of the bundles would be unloaded. So calling AssetBundle.Unload function while some of the bundles are still being loaded will block the execution of the rest of the code until all bundles are loaded. This will add a performance hiccup. This has been reworked in Unity 5.

Если вам нужно отследить то, какие пакеты ассетов были вами загружены, тогда вы можете воспользоваться wrapper классом, который поможет вам управлять своими загрузками следующим образом:

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 является статичным, и любые пакеты ассетов, на которые вы ссылаетесь, не уничтожатся при загрузке новой сцены. Используйте этот класс в качестве путеводителя, но как было сказано вначале, будет лучше если вы выгрузите пакеты ассетов (AssetBundles) сразу после их использования. Вы всегда можете клонировать ранее инстанциированный объект, устраняя необходимость в повторной загрузке пакетов ассетов (AssetBundles).

Загрузка и выгрузка объектов из AssetBundle
Сохранение и загрузка бинарных данных в AssetBundle