Unity3D关于AssetBundle框架设计(B)

一、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章

猜你喜欢

转载自blog.csdn.net/xiaochenXIHUA/article/details/83684695