美文网首页
二、资源管理5:ab包普通的加载流程

二、资源管理5:ab包普通的加载流程

作者: GameObjectLgy | 来源:发表于2023-08-03 15:23 被阅读0次
    一、加载流程概述

    1.加载主包和配置文件。因为加载所有包是 都得判断 通过它才能得到依赖信息。
    2.加载指定包的依赖包。
    3.加载目标包。
    4.按需要来实例化加载出来的资源。
    5.按需要使用同步与异步的加载方法。
    6.AB包内存镜像文件不能够重复加载否则会报错。因此可以使用一个字典来维护保证加载的唯一性。

    二、示例代码

    代码主要对外接口功能是LoadRes和LoadResAsync。
    可作为简单的资源加载管理器,但是商业项目上是不太够用的。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Events;
    
    //知识点
    //字典
    //协程
    //AB包相关API
    //委托
    //lambda表达式
    //单例模式基类——>观看Unity小框架视频 进行学习
    public class ABMgr : SingleonAutoMon<ABMgr>
    {
        //主包
        private AssetBundle mainAB = null;
        //主包依赖获取配置文件
        private AssetBundleManifest manifest = null;
    
        //选择存储 AB包的容器
        //AB包不能够重复加载 否则会报错。使用这个字典结构来保证只加载了一次ab包。
        //字典知识 用来存储 AB包对象
        private Dictionary<string, AssetBundle> abDic = new Dictionary<string, AssetBundle>();
    
        /// <summary>
        /// 获取AB包加载路径
        /// </summary>
        private string PathUrl
        {
            get
            {
                return Application.streamingAssetsPath + "/";
            }
        }
    
        /// <summary>
        /// 主包名 根据平台不同 报名不同
        /// </summary>
        private string MainName
        {
            get
            {
    #if UNITY_IOS
                return "IOS";
    #elif UNITY_ANDROID
                return "Android";
    #else
                return "StandaloneWindows";
    #endif
            }
        }
    
        /// <summary>
        /// 加载主包 和 配置文件
        /// 因为加载所有包是 都得判断 通过它才能得到依赖信息
        /// 所以写一个方法
        /// </summary>
        private void LoadMainAB()
        {
            if( mainAB == null )
            {
                mainAB = AssetBundle.LoadFromFile( PathUrl + MainName);
                manifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
            }
        }
    
        /// <summary>
        /// 加载指定包的依赖包
        /// </summary>
        /// <param name="abName"></param>
        private void LoadDependencies(string abName)
        {
            //加载主包
            LoadMainAB();
            //获取依赖包
            string[] strs = manifest.GetAllDependencies(abName);
            for (int i = 0; i < strs.Length; i++)
            {
                if (!abDic.ContainsKey(strs[i]))
                {
                    AssetBundle ab = AssetBundle.LoadFromFile(PathUrl + strs[i]);
                    abDic.Add(strs[i], ab);
                }
            }
        }
    
        /// <summary>
        /// 泛型资源同步加载
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="abName"></param>
        /// <param name="resName"></param>
        /// <returns></returns>
        public T LoadRes<T>(string abName, string resName) where T:Object
        {
            //加载依赖包
            LoadDependencies(abName);
            //加载目标包
            if ( !abDic.ContainsKey(abName) )
            {
                AssetBundle ab = AssetBundle.LoadFromFile(PathUrl + abName);
                abDic.Add(abName, ab);
            }
    
            //得到加载出来的资源
            T obj = abDic[abName].LoadAsset<T>(resName);
            //如果是GameObject 因为GameObject 100%都是需要实例化的
            //所以我们直接实例化
            if (obj is GameObject)
                return Instantiate(obj);
            else
                return obj;
        }
    
        /// <summary>
        /// Type同步加载指定资源
        /// </summary>
        /// <param name="abName"></param>
        /// <param name="resName"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public Object LoadRes(string abName, string resName, System.Type type) 
        {
            //加载依赖包
            LoadDependencies(abName);
            //加载目标包
            if (!abDic.ContainsKey(abName))
            {
                AssetBundle ab = AssetBundle.LoadFromFile(PathUrl + abName);
                abDic.Add(abName, ab);
            }
    
            //得到加载出来的资源
            Object obj = abDic[abName].LoadAsset(resName, type);
            //如果是GameObject 因为GameObject 100%都是需要实例化的
            //所以我们直接实例化
            if (obj is GameObject)
                return Instantiate(obj);
            else
                return obj;
        }
    
        /// <summary>
        /// 名字 同步加载指定资源
        /// </summary>
        /// <param name="abName"></param>
        /// <param name="resName"></param>
        /// <returns></returns>
        public Object LoadRes(string abName, string resName)
        {
            //加载依赖包
            LoadDependencies(abName);
            //加载目标包
            if (!abDic.ContainsKey(abName))
            {
                AssetBundle ab = AssetBundle.LoadFromFile(PathUrl + abName);
                abDic.Add(abName, ab);
            }
    
            //得到加载出来的资源
            Object obj = abDic[abName].LoadAsset(resName);
            //如果是GameObject 因为GameObject 100%都是需要实例化的
            //所以我们直接实例化
            if (obj is GameObject)
                return Instantiate(obj);
            else
                return obj;
        }
    
        /// <summary>
        /// 泛型异步加载资源
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="abName"></param>
        /// <param name="resName"></param>
        /// <param name="callBack"></param>
        public void LoadResAsync<T>(string abName, string resName, UnityAction<T> callBack) where T:Object
        {
            StartCoroutine(ReallyLoadResAsync<T>(abName, resName, callBack));
        }
        //正儿八经的 协程函数
        private IEnumerator ReallyLoadResAsync<T>(string abName, string resName, UnityAction<T> callBack) where T : Object
        {
            //加载依赖包
            LoadDependencies(abName);
            //加载目标包
            if (!abDic.ContainsKey(abName))
            {
                AssetBundle ab = AssetBundle.LoadFromFile(PathUrl + abName);
                abDic.Add(abName, ab);
            }
            //异步加载包中资源
            AssetBundleRequest abq = abDic[abName].LoadAssetAsync<T>(resName);
            yield return abq;
    
            if (abq.asset is GameObject)
                callBack(Instantiate(abq.asset) as T);
            else
                callBack(abq.asset as T);
        }
    
        /// <summary>
        /// Type异步加载资源
        /// </summary>
        /// <param name="abName"></param>
        /// <param name="resName"></param>
        /// <param name="type"></param>
        /// <param name="callBack"></param>
        public void LoadResAsync(string abName, string resName, System.Type type, UnityAction<Object> callBack)
        {
            StartCoroutine(ReallyLoadResAsync(abName, resName, type, callBack));
        }
    
        private IEnumerator ReallyLoadResAsync(string abName, string resName, System.Type type, UnityAction<Object> callBack)
        {
            //加载依赖包
            LoadDependencies(abName);
            //加载目标包
            if (!abDic.ContainsKey(abName))
            {
                AssetBundle ab = AssetBundle.LoadFromFile(PathUrl + abName);
                abDic.Add(abName, ab);
            }
            //异步加载包中资源
            AssetBundleRequest abq = abDic[abName].LoadAssetAsync(resName, type);
            yield return abq;
    
            if (abq.asset is GameObject)
                callBack(Instantiate(abq.asset));
            else
                callBack(abq.asset);
        }
    
        /// <summary>
        /// 名字 异步加载 指定资源
        /// </summary>
        /// <param name="abName"></param>
        /// <param name="resName"></param>
        /// <param name="callBack"></param>
        public void LoadResAsync(string abName, string resName, UnityAction<Object> callBack)
        {
            StartCoroutine(ReallyLoadResAsync(abName, resName, callBack));
        }
    
        private IEnumerator ReallyLoadResAsync(string abName, string resName, UnityAction<Object> callBack)
        {
            //加载依赖包
            LoadDependencies(abName);
            //加载目标包
            if (!abDic.ContainsKey(abName))
            {
                AssetBundle ab = AssetBundle.LoadFromFile(PathUrl + abName);
                abDic.Add(abName, ab);
            }
            //异步加载包中资源
            AssetBundleRequest abq = abDic[abName].LoadAssetAsync(resName);
            yield return abq;
    
            if (abq.asset is GameObject)
                callBack(Instantiate(abq.asset));
            else
                callBack(abq.asset);
        }
    
        //卸载AB包的方法
        public void UnLoadAB(string name)
        {
            if( abDic.ContainsKey(name) )
            {
                abDic[name].Unload(false);
                abDic.Remove(name);
            }
        }
    
        //清空AB包的方法
        public void ClearAB()
        {
            AssetBundle.UnloadAllAssetBundles(false);
            abDic.Clear();
            //卸载主包
            mainAB = null;
        }
    }
    
    

    相关文章

      网友评论

          本文标题:二、资源管理5:ab包普通的加载流程

          本文链接:https://www.haomeiwen.com/subject/ccxfoltx.html