1. 程式人生 > >Unity5.4 Assetbundles官方說明六(保留下載的AssetBundle)

Unity5.4 Assetbundles官方說明六(保留下載的AssetBundle)

轉載請註明出處!

  Unity只允許AssetBundle在程式中例項化一次,如果之前一個AssetBundle從WWW加載出來並沒有釋放(Unload),那麼就不能再次載入同一個AssetBundle,例如我們已經通過以下指令碼獲取了AssetBundle資源包物件:
AssetBundle bundle = www.assetBundle;

然後在這個資源包沒有釋放的情況下,又通過這個指令碼獲取同一個資源包物件,那麼第二次返回的bundle值會是null,而且將會丟擲以下錯誤:
Cannot load cached AssetBundle. A file of the same name is already loaded from another AssetBundle

這就要求當我們載入了一次資源包,在解除安裝前就不能再次載入。在此建議:一旦資源包中需要的資源被載入完成,就立馬卸釋放掉AssetBundle。
注意:在Unity5之前的版本中,任何AssetBundle資源包被解除安裝前需要完成資源包的載入才行,即只有載入完資源包才能對其釋放。因此當某些資源包正在載入的時候呼叫AssetBundle.Unload()方法釋放資源,這樣會阻塞下面指令碼程式碼的執行,直到所有的資源包載入完為止,這樣會導致程式執行時卡頓。不過在Unity5的版本中,這個問題已被修改。

如果想保持下載的AssetBundle資源包,可以用如下的類來管理下載的資料,可直接複製到專案中:
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;

static public class AssetBundleManager
{
/// <summary>
/// 儲存AssetBundle資源包引用的容器,其中key值是下載地址+版本號的組合,value值是AssetBundleRef類資料
/// </summary>
static private Dictionary<string, AssetBundleRef> dictAssetBundleRefs;
static AssetBundleManager()
{
dictAssetBundleRefs = new Dictionary<string, AssetBundleRef>();
}

/// <summary>
/// 包含AssetBundle引用的類,其中包括url地址和version版本號
/// </summary>
private class AssetBundleRef
{
public AssetBundle assetBundle = null; //資源包
public int version; //版本號
public string url; //下載地址
public AssetBundleRef(string strUrlIn, int intVersionIn)
{
url = strUrlIn;
version = intVersionIn;
}
};
/// <summary>
/// 從儲存的容器中獲取資源包
/// </summary>
/// <param name="url">下載地址</param>
/// <param name="version">版本號</param>
/// <returns>返回獲取的資源包</returns>
public static AssetBundle getAssetBundle(string url, int version)
{
string keyName = url + version.ToString();
AssetBundleRef abRef;
if (dictAssetBundleRefs.TryGetValue(keyName, out abRef)) //將空的abRef傳遞進去
return abRef.assetBundle;
else
return null;
}
/// <summary>
/// 下載AssetBundle資源包
/// </summary>
/// <param name="url">下載地址</param>
/// <param name="version">版本號</param>
/// <returns>返回下載的資源包</returns>
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);
}
}
}
/// <summary>
/// 刪除容器中儲存的資源資料
/// </summary>
/// <param name="url">路徑地址</param>
/// <param name="version">版本號</param>
/// <param name="allObjects">表示是否刪除資源包的所有資源</param>
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);
}
}
}


在此列舉一個例子來使用上面管理Assetbundle的類:
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, true);
}
}

注意:上面例子中的AssetBundleManager類是靜態的,當載入一個新的場景時,引用的類中任何資源包資訊都不會被銷燬。
  我將在第十一篇中給出完整的專案原始碼(包括資源的打包、下載資源包、載入資源包、獲取資源幾依賴資源、使用資源等)。下一篇將講解關於AssetBundle中儲存和載入二進位制資料。
--------------------- 
作者:IQ007偉哥 
來源:CSDN 
原文:https://blog.csdn.net/u010377179/article/details/52922716 
版權宣告:本文為博主原創文章,轉載請附上博文連結!