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