Unity3D關於AssetBundle框架設計(B)
阿新 • • 發佈:2018-12-09
一、AssetBundle整體管理
《1》AssetBundle框架的整體管理包含兩大部分
①主程式的AssetBundleMgr指令碼,通過呼叫輔助類“ABManifestLoader”來讀取Untiy提供的Manifest清單檔案。
②主程式的MutiABMgr指令碼,通過獲取Manifest清單檔案,迴圈遍歷需要載入AB包所有的底層依賴包。然後給每個AB包都記錄相關依賴於引用關係,這些關係都記錄在對應的ABRelation物件中。
框架資源包地址:https://download.csdn.net/download/xiaochenxihua/10761774
/*** * * Title: "AssetBundle工具包"專案 * 輔助類: 讀取AssetBundles 依賴關係檔案:Win.Manifest * * Description: * 功能: * Win.Manifest 檔案是Unity提供的一份確定所有 * Assetbundle 包檔案所有依賴關係的清單檔案。 * * Date: 2018 * * Version: 1.0 * * Modify Recorder: * */ using System.Collections; using System.Collections.Generic; using UnityEngine; namespace ABTools { public class ABManifestLoader:System.IDisposable { //本類例項 private static ABManifestLoader _Instance; //AssetBundle(清單檔案)系統類 private AssetBundleManifest _ManifestObj; //AssetBundle 清單檔案路徑 private string _StrManifestPath; //讀取Manifest清單檔案的AssetBundle private AssetBundle _ABReadManifest; //是否載入完成 private bool _IsLoadFinish; /* 只讀屬性 */ public bool IsLoadFinish{ get { return _IsLoadFinish; } } #region /// <summary> /// 建構函式 /// </summary> private ABManifestLoader() { //確定清單WWW下載路徑 _StrManifestPath = PathTools.GetWWWPath() + "/" + PathTools.GetPlatformName(); _ManifestObj = null; _ABReadManifest = null; _IsLoadFinish = false; } /// <summary> /// 得到本類例項 /// </summary> /// <returns></returns> public static ABManifestLoader GetInstance() { if(_Instance==null) { _Instance = new ABManifestLoader(); } return _Instance; } #endregion /// 載入Manifest清單檔案 public IEnumerator LoadManifestFile(){ using (WWW www = new WWW(_StrManifestPath)){ yield return www; if (www.progress >= 1){ //載入完成,獲取AssetBundel例項 AssetBundle abObj = www.assetBundle; if (abObj != null){ _ABReadManifest = abObj; _ManifestObj=_ABReadManifest.LoadAsset(ABDefine.ASSETBUNDLE_MANIFEST) as AssetBundleManifest; _IsLoadFinish = true; } else{ Debug.LogError(GetType() + "/LoadManifestFile()/WWW 下載出錯,請檢查 AssetBundle URL :" + _StrManifestPath + " 錯誤資訊: " + www.error); } } }//using_end } /// <summary> /// 返回"AssetBundleManifest"系統類例項 /// </summary> /// <returns></returns> public AssetBundleManifest GetABManifest() { if (_IsLoadFinish) { if (_ManifestObj != null) { return _ManifestObj; } else { Debug.Log(GetType() + "/GetABManifest()/_ManifestObj==null 。請檢查原因!"); } } else { Debug.Log(GetType() + "/GetABManifest()/Manifest沒有載入完畢,請檢查原因!"); } return null; } /// <summary> /// 獲取指定AssetBundle包所有依賴項 /// </summary> /// <param name="abName"></param> /// <returns></returns> public string[] RetrivalDependences(string abName) { if (_ManifestObj != null && !string.IsNullOrEmpty(abName)) { return _ManifestObj.GetAllDependencies(abName); } return null; } /// <summary> /// 釋放資源(解除安裝Manifest所有資源) /// </summary> public void Dispose() { if (_ABReadManifest!=null) { _ABReadManifest.Unload(true); } } }//Class_end }
/*** * * Title: "AssetBundle工具包"專案 * 輔助類; AssetBundle 關係類 * * Description: * 功能: * 1:確定指定AssetBundle 類的依賴包。 * 2:確定指定AssetBundle 類的引用包(被依賴包) * * Date: 2018 * * Version: 1.0 * * Modify Recorder: * */ using System.Collections; using System.Collections.Generic; using UnityEngine; namespace ABTools { public class ABRelation { //AssetBundle 名稱 private string _ABName; //所有依賴包名 private List<string> _LisAllDependenceAB; //所有引用包名 private List<string> _LisALLReferenceAB; /// 建構函式 public ABRelation(string abName) { _ABName = abName; _LisAllDependenceAB = new List<string>(); _LisALLReferenceAB = new List<string>(); } /* 依賴關係 */ #region 依賴關係 /// <summary> /// 增加依賴關係 /// </summary> /// <param name="abName">Assetbundle 名稱</param> public void AddDependence(string abName) { if (!_LisAllDependenceAB.Contains(abName)) { _LisAllDependenceAB.Add(abName); } } /// <summary> /// 移除依賴關係 /// </summary> /// <param name="abName"></param> /// <returns> /// true: 此AssetBundle沒有依賴項 /// false: 此AssetBundle還有其他的依賴項 /// </returns> public bool RemoveDependence(string abName) { if (_LisAllDependenceAB.Contains(abName)) { _LisAllDependenceAB.Remove(abName); } if (_LisAllDependenceAB.Count > 0) { return false; } else { return true; } } /// <summary> /// 獲取所有的依賴關係 /// </summary> /// <returns></returns> public List<string> GetAllDependences() { return _LisAllDependenceAB; } #endregion /* 引用關係 */ #region 引用關係 /// <summary> /// 增加引用關係 /// </summary> /// <param name="abName"></param> public void AddReference(string abName) { if (!_LisALLReferenceAB.Contains(abName)) { _LisALLReferenceAB.Add(abName); } } /// <summary> /// 移除引用關係 /// </summary> /// <param name="abName"></param> /// <returns> /// true: 此AssetBundle沒有引用項 /// false: 此AssetBundle還有其他的引用項 /// </returns> public bool RemoveReference(string abName) { if (_LisALLReferenceAB.Contains(abName)) { _LisALLReferenceAB.Remove(abName); } if (_LisALLReferenceAB.Count > 0) { return false; } else { return true; } } /// <summary> /// 獲取所有的引用關係(集合) /// </summary> /// <returns></returns> public List<string> GetAllReference() { return _LisALLReferenceAB; } #endregion }//Class_end }
/*** * * Title: "AssetBundle工具包"專案 * 第4層(最後層): 所有“場景”的AssetBundle的管理 * * Description: * 功能: * 1:以“場景”為單位,管理整個專案所有的AssetBundle 包。 * 2:提取“Menifest清單檔案”,快取本類。 * * Date: 2018 * * Version: 1.0 * * Modify Recorder: * */ using System.Collections; using System.Collections.Generic; using UnityEngine; namespace ABTools { public class AssetBundleMgr: MonoBehaviour{ //本類例項 private static AssetBundleMgr _Instance; //場景集合 private Dictionary<string, MultiABMgr> _DicAllScenes = new Dictionary<string, MultiABMgr>(); //AssetBundle(清單檔案)系統類(包含本專案所有依賴項) private AssetBundleManifest _ManifestObj=null; #region private AssetBundleMgr() { } /// <summary> /// 得到本類例項 /// </summary> /// <returns></returns> public static AssetBundleMgr GetInstance() { if (_Instance==null) { _Instance = new GameObject("_AssetBundleMgr").AddComponent<AssetBundleMgr>(); } return _Instance; } private void Awake() { // 載入Manifest清單檔案 StartCoroutine(ABManifestLoader.GetInstance().LoadManifestFile()); } #endregion /// <summary> /// 下載AssetBundle指定包 /// </summary> /// <param name="sceneName">場景名稱</param> /// <param name="abName">AssetBundle名稱</param> /// <param name="loadAllABCompleteHandle">AssetBundle名稱</param> public IEnumerator LoadAssetBundlePackage(string sceneName,string abName,DelLoadComplete loadAllABCompleteHandle) { //引數檢查 if (string.IsNullOrEmpty(sceneName) || string.IsNullOrEmpty(abName)) { Debug.LogError(GetType()+ "/LoadAssetBundlePackage()/scenenName Or abName is Null ,請檢查!"); yield return null; } //等待Manifest清單載入完成 while (!ABManifestLoader.GetInstance().IsLoadFinish) yield return null; //獲取“AssetBundle(清單檔案)系統類” _ManifestObj = ABManifestLoader.GetInstance().GetABManifest(); //引數檢查 if (_ManifestObj==null) { Debug.LogError(GetType() + "/LoadAssetBundlePackage()/_ManifestObj==null,請先確保載入Manifest清單檔案!"); yield return null; } //如果不包含指定場景,則先建立 if (!_DicAllScenes.ContainsKey(sceneName)) { CreateScenesAB(sceneName,abName, loadAllABCompleteHandle); } //呼叫下一層(“多AssetBundle管理”類) MultiABMgr tmpMultiABMgrObj =_DicAllScenes[sceneName]; if (tmpMultiABMgrObj==null) { Debug.LogError(GetType()+ "/LoadAssetBundlePackage()/tmpMultiABMgrObj==null , 請檢查!"); } yield return tmpMultiABMgrObj.LoadAssetBundles(abName); } /// <summary> /// 建立一個“場景AssetBundle”且加入集合中 /// </summary> /// <param name="scensName"></param> private void CreateScenesAB(string scensName,string abName, DelLoadComplete loadAllABCompleteHandle) { MultiABMgr multiABMgeObj = new MultiABMgr(scensName, abName,loadAllABCompleteHandle); _DicAllScenes.Add(scensName,multiABMgeObj); } /// <summary> /// 載入(AB包內)資源 /// </summary> /// <param name="scenesName">場景名稱</param> /// <param name="abName">AssetBundle 名稱</param> /// <param name="assetName">資源名稱</param> /// <param name="isCache">是否使用(資源)快取</param> /// <returns></returns> public UnityEngine.Object LoadAsset(string scenesName,string abName,string assetName, bool isCache) { if (_DicAllScenes.ContainsKey(scenesName)) { MultiABMgr multiObj = _DicAllScenes[scenesName]; return multiObj.LoadAsset(abName,assetName,isCache); } Debug.LogError(GetType()+"/LoadAsset()/找不到場景: "+scenesName+" ,無法載入AssetBundle 資源,請檢查!"); return null; } /// <summary> /// 釋放一個場景中所有的資源 /// </summary> /// <param name="scenesName"></param> /// <returns></returns> public void DisposeAllAssets(string scenesName) { if (_DicAllScenes.ContainsKey(scenesName)) { MultiABMgr multiObj = _DicAllScenes[scenesName]; multiObj.DisposeAllAsset(); } else { Debug.LogError(GetType() + "/DisposeAllAsset()/找不到場景: " + scenesName + " ,無法釋放資源,請檢查!"); } } }//Class_end }
/***
*
* Title: "AssetBundle工具包"專案
* 第3層: (一個場景中)多AssetBundle管理
*
* Description:
* 功能:
* 1:獲得包之間的依賴關係。
* 2:管理具備依賴與引用關係的AssetBundle包的自動連鎖載入機制。
*
*
* Date: 2018
*
* Version: 1.0
*
* Modify Recorder:
*
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace ABTools
{
public class MultiABMgr
{
//當前 "單個AB載入實現類"
private SingleABLoader _CurrentSingleABLoader;
//"單個AB載入實現類"快取集合(作用: 快取AB包,防止重複載入)
//第1個引數表示“AB包名稱”,第2引數是“單個AB載入實現類”
private Dictionary<string, SingleABLoader> _DicSingleABLoaderCache;
//當前場景名稱
private string _CurrentScenesName;
//當前AssetBundle 名稱
private string _CurrentABName;
//AB包名稱與對應依賴關係集合
private Dictionary<string, ABRelation> _DicABRelation;
//委託: 所有的AB包載入完成
private DelLoadComplete _LoadAllABPackageCompleteHandle;
/// <summary>
/// 建構函式
/// </summary>
/// <param name="scenesName">場景名稱</param>
/// <param name="abName">AssetBundle名稱</param>
/// /// <param name="loadAllABPackageCompletteHandle">委託:載入所有AB包完成</param>
public MultiABMgr(string scenesName,string abName,DelLoadComplete loadAllABPackageCompletteHandle)
{
_CurrentScenesName = scenesName;
_CurrentABName = abName;
_DicSingleABLoaderCache = new Dictionary<string, SingleABLoader>();
_DicABRelation = new Dictionary<string, ABRelation>();
//委託:載入所有AB包完成
_LoadAllABPackageCompleteHandle=loadAllABPackageCompletteHandle;
}
/// <summary>
/// 完成指定AB包的呼叫
/// </summary>
/// <param name="abName"></param>
private void CompletLoadAB(string abName)
{
if (abName.Equals(_CurrentABName))
{
if (_LoadAllABPackageCompleteHandle!=null)
{
_LoadAllABPackageCompleteHandle(abName);
}
}
}
/// <summary>
/// 載入AB包
/// </summary>
/// <param name="abName"></param>
/// <returns></returns>
public IEnumerator LoadAssetBundles(string abName)
{
if (!_DicABRelation.ContainsKey(abName))
{
ABRelation abRelationObj = new ABRelation(abName);
_DicABRelation.Add(abName,abRelationObj);
}
ABRelation tmpABRelationObj = _DicABRelation[abName];
//得到指定AB包所有的依賴關係
string[] strDepencedArray = ABManifestLoader.GetInstance().RetrivalDependences(abName);
foreach (string item_Depence in strDepencedArray)
{
//新增“依賴”項
tmpABRelationObj.AddDependence(item_Depence);
//新增“引用”項
yield return LoadReference(item_Depence,abName);
}
//真正的AB包載入
if (_DicSingleABLoaderCache.ContainsKey(abName))
{
yield return _DicSingleABLoaderCache[abName].LoadAssetBundle();
}
else {
_CurrentSingleABLoader = new SingleABLoader(abName, CompletLoadAB);
_DicSingleABLoaderCache.Add(abName,_CurrentSingleABLoader);
yield return _CurrentSingleABLoader.LoadAssetBundle();
}
}//Method_end
/// <summary>
/// 載入引用AB包
/// </summary>
/// <param name="abName">AB包名稱</param>
/// <param name="refABName">引用AB包名稱</param>
/// <returns></returns>
private IEnumerator LoadReference(string abName,string refABName)
{
//AB包已經載入了
if (_DicABRelation.ContainsKey(abName))
{
ABRelation tmpABRelationObj = _DicABRelation[abName];
//新增AB包的引用關係(被依賴)
tmpABRelationObj.AddReference(refABName);
}
else {
ABRelation tmpABRelationObj = new ABRelation(abName);
tmpABRelationObj.AddReference(refABName);
_DicABRelation.Add(abName,tmpABRelationObj);
//開始載入依賴的包(注意: 這是一個“遞迴”呼叫)
yield return LoadAssetBundles(abName);
}
}//Method_end
/// <summary>
/// 載入(AB包內)資源
/// </summary>
/// <param name="abName">AssetBundle 名稱</param>
/// <param name="assetName">資源名稱</param>
/// <param name="isCache">是否使用(資源)快取</param>
/// <returns></returns>
public UnityEngine.Object LoadAsset(string abName, string assetName, bool isCache)
{
foreach (string item_AbName in _DicSingleABLoaderCache.Keys)
{
if(item_AbName==abName)
{
return _DicSingleABLoaderCache[item_AbName].LoadAsset(assetName,isCache);
}
}
Debug.LogError(GetType() + "/LoadAsset()/找不到Assetbundle 包,無法載入資源,請檢查! abName= "+abName+ " assetName="+assetName);
return null;
}
/// <summary>
/// 釋放場景中所有資源
/// </summary>
/// <returns></returns>
public void DisposeAllAsset()
{
//逐一釋放所有載入過的AssetBundle包資源
try
{
foreach (SingleABLoader item_sABLoader in _DicSingleABLoaderCache.Values)
{
item_sABLoader.DisposeALL();
}
}
finally
{
_DicSingleABLoaderCache.Clear();
_DicSingleABLoaderCache = null;
/* 釋放其他物件佔用 */
_DicABRelation.Clear();
_DicABRelation = null;
_CurrentScenesName = null;
_CurrentABName = null;
_LoadAllABPackageCompleteHandle = null;
//解除安裝沒有使用到的資源
Resources.UnloadUnusedAssets();
//強制垃圾收集
System.GC.Collect();
}
}
}//Class_end
}
注:本內容來自《Untiy3D/2D遊戲開發從0到1》 第30章