首页 > 其他分享 >Unity 热更--AssetBundle学习笔记 1.0【AB包资源加载工具类的实现】

Unity 热更--AssetBundle学习笔记 1.0【AB包资源加载工具类的实现】

时间:2024-05-03 11:23:01浏览次数:21  
标签:AB 1.0 string -- GameObject resName abName 加载

工具类封装

通过上文中对AB包加载API的了解和简单使用,对AB包资源加载的几种方法进行封装,将其写入单例类中,如代码展示。

确保每个AB资源包只加载一次:

在LoadAssetBundleManager 单例工具类中,首先提供基本的AB包及其AB包依赖包的加载方法,为保持AssetBundle只加载一次,使用DIctionary键值对来记录已经加载出的AB资源。

主包路径的灵活获取:

加载主包路径的获取,采用宏来对不同的打包平台来选择对应的主包名称。(可自行定义使用)

依赖包的加载:

通过加载主包中的AssetBundleManifest 来获取目标AB包的依赖AB包名称,根据名称进行逐个加载。

加载方法有异步和同步两种:

异步加载是在AB包获取之后进行的资源的异步加载,和同步加载一样有对加载函数进行3此重载。分别为根据名称加载,

泛型加载(C#中使用方便),根据类型加载(供Lua调用)。

卸载方法的实现:单个AB资源包卸载和所有资源包卸载两种方式。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

namespace BaseFramework
{
    /// <summary>
    /// 加载AssetBundle工具类 单例 
    /// </summary>
    public class LoadAssetBundleManager: SingletonAutoMono<LoadAssetBundleManager>
    {
        //主AB包 
        private AssetBundle mainAssetBundle = null;
        //包体依赖manifest 
        private AssetBundleManifest assetBundleManifest = null;
        
        //防止AB包重复加载 对已经加载的AB包存储
        private Dictionary<string, AssetBundle> assetBundlesDic = new Dictionary<string, AssetBundle>();

        //加载路径
        private string pathAssetBundle
        {
            get
            {
                return Application.streamingAssetsPath + "/";
            }
        }
        //主包名称
        private string mainAssetBundleName
        {
            get
            {
#if UnITY_IOS
                return "IOS";
#elif UNITY_ANDROID
                return "Android";
#else
                return "StandaloneWindows";
#endif
            }
        }

        /// <summary>
        /// 根据名称加载AB包 也会检查相关依赖包 进行加载
        /// </summary>
        /// <param name="assetBundleName">AB包的名称</param>
        public void LoadAssetBundle(string assetBundleName)
        {
            if (!assetBundlesDic.ContainsKey(assetBundleName))
            {
                 AssetBundle resAssetBundle = AssetBundle.LoadFromFile(pathAssetBundle+assetBundleName);
                 assetBundlesDic.Add(assetBundleName,resAssetBundle);
            }
            //加载主资源包 从主资源包中获取对manifest
            if (mainAssetBundle == null)
            {
                mainAssetBundle = AssetBundle.LoadFromFile(pathAssetBundle + mainAssetBundleName);
                assetBundleManifest = mainAssetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
            }
            //加载目标资源包的依赖AB
            string[] dependencies = assetBundleManifest.GetAllDependencies(assetBundleName);
            foreach (var dependency in dependencies)
            {
                AssetBundle currentAB = null;
                if (!assetBundlesDic.ContainsKey(dependency))
                {
                    //加载依赖的ab包
                    currentAB = AssetBundle.LoadFromFile(pathAssetBundle + dependency); 
                    assetBundlesDic.Add(dependency,currentAB);
                }
            }
        }

        /// <summary>
        /// 从AB包中获取具体资源
        /// </summary>
        /// <param name="abName">AB包名称</param>
        /// <param name="resName">资源名称</param>
        /// <returns>Object资源</returns>
        public Object LoadResource(string abName, string resName)
        {
            LoadAssetBundle(abName);
            Object resObj = null;
            resObj = assetBundlesDic[abName].LoadAsset(resName);
            return resObj;
        }
        /// <summary>
        /// 泛型方法重载
        /// </summary>
        public T LoadResource<T>(string abName, string resName) where T:Object
        {
            LoadAssetBundle(abName);
            T res = assetBundlesDic[abName].LoadAsset<T>(resName);
            return res;
        }
        /// <summary>
        /// 根据资源类型重载方法
        /// </summary>
        public Object LoadResource(string abName, string resName, System.Type type)
        {
            LoadAssetBundle(abName);
            Object obj = assetBundlesDic[abName].LoadAsset(resName, type);
            return obj;
        }
        //--------------------------------------------------------
        //同步加载的AB包 异步加载res资源
        public void LoadResourceAsync(string abName, string resName, UnityAction<Object> callback)
        {
            StartCoroutine(LoadResourceIEn(abName, resName, callback));
        }
        //异步加载协程
        private IEnumerator LoadResourceIEn(string abName, string resName, UnityAction<Object> callback)
        {
            LoadAssetBundle(abName);
            AssetBundleRequest request = assetBundlesDic[abName].LoadAssetAsync(resName);
            yield return request;
            callback(request.asset);
        }
        //根据泛型来异步加资源
        public void LoadResourceAsync<T>(string abName, string resName, UnityAction<Object> callback) where  T : Object
        {
            StartCoroutine(LoadResourceIEn<T>(abName, resName, callback));
        }
        //异步加载协程
        private IEnumerator LoadResourceIEn<T>(string abName, string resName, UnityAction<Object> callback) where T :Object
        {
            LoadAssetBundle(abName);
            AssetBundleRequest request = assetBundlesDic[abName].LoadAssetAsync<T>(resName);
            yield return request;
            callback(request.asset);
        }
        //根据res类型异步加载资源
        //根据泛型来异步加资源
        public void LoadResourceAsync(string abName, string resName, System.Type type,UnityAction<Object> callback) 
        {
            StartCoroutine(LoadResourceIEn(abName, resName, type, callback));
        }
        //异步加载协程
        private IEnumerator LoadResourceIEn(string abName, string resName, System.Type type, UnityAction<Object> callback) 
        {
            LoadAssetBundle(abName);
            AssetBundleRequest request = assetBundlesDic[abName].LoadAssetAsync(resName,type);
            yield return request;
            callback(request.asset);
        }
        //资源包的卸载
        public void UnLoadAssetBundle(string abName)
        {
            if (assetBundlesDic.ContainsKey(abName))
            {
                assetBundlesDic[abName].Unload(false);
                assetBundlesDic.Remove(abName);
            }
        }
        //卸载所有加载的资源包
        public void UnLoadAllAssetBundle()
        {
            AssetBundle.UnloadAllAssetBundles(false);
            assetBundlesDic.Clear();
            mainAssetBundle = null;
            assetBundleManifest = null;
        }

    }
}

该Manager继承的单例脚本:

using UnityEngine;

namespace BaseFramework
{
    public class SingletonAutoMono<T> : MonoBehaviour where T : MonoBehaviour
    {
        private static T instance;

        public static T Instance()
        {
            if (instance == null)
            {
                GameObject gameObject = new GameObject();
                gameObject.name = typeof(T).ToString();
                DontDestroyOnLoad(gameObject);
                instance = gameObject.AddComponent<T>();
            }
            return instance;
        }

    }
}

在测试脚本中我们使用6种不同的加载方式进行cube的加载,完成方法测试。

 //测试使用工具类加载
            Object cube = LoadAssetBundleManager.Instance().LoadResource("model", "cube");
            if (cube is GameObject)
            {
                GameObject cube1 = cube as GameObject;
                cube1.transform.position = Vector3.up;
                Instantiate(cube1);
            }
            //异步加载
            LoadAssetBundleManager.Instance().LoadResourceAsync("model", "cube", (obj) =>
            {
                GameObject cube1 = obj as GameObject;
                cube1.transform.position = new Vector3(0,1.5f,0);
                Instantiate(cube1);
            });
            
            //重新测试
            //使用泛型
            GameObject cube2 = LoadAssetBundleManager.Instance().LoadResource<GameObject>("model", "cube");
            cube2.transform.position = Vector3.left;
            Instantiate(cube2);
        
            
             LoadAssetBundleManager.Instance().LoadResourceAsync<GameObject>("model", "cube", (obj) =>
             {
                 GameObject cube1 = obj as GameObject;
                 cube1.transform.position = Vector3.right;
                 Instantiate(cube1);
             });
             
             //通过类型加载测试
             GameObject cube3 = LoadAssetBundleManager.Instance().LoadResource("model", "cube",typeof(GameObject)) as GameObject;
             cube3.transform.position = new Vector3(0,-1.5f,0);
             Instantiate(cube3);

             LoadAssetBundleManager.Instance().LoadResourceAsync("model", "cube",typeof(GameObject), (obj) =>
             {
                 GameObject cube1 = obj as GameObject;
                 cube1.transform.position = Vector3.zero;
                 Instantiate(cube1);
             });
             LoadAssetBundleManager.Instance().UnLoadAllAssetBundle();

image-20240502231345546

标签:AB,1.0,string,--,GameObject,resName,abName,加载
From: https://www.cnblogs.com/TonyCode/p/18170759

相关文章

  • 操作系统总结
    首先,我们从概念说起,操作系统是一种系统软件,它是计算机硬件和其他软件之间的桥梁。它的作用便是管理和控制计算机的硬件资源,如处理器、内存、硬盘等等,操作系统的主要任务又包括进程管理、内存管理、文件系统管理、设备管理和网络管理等。操作系统的发展是从微机操作系统到多处理器......
  • [题解]ABC337E Bad Juice
    ABC337EBadJuice一开始的想法如下:就是利用二分法,对于一个区间\([l,r]\),分成\([l,mid-1],[mid,r-1]\)两部分,各找两个朋友喝,右边还空出一个\(r\),如果前面两个朋友都没中毒,那说明\(r\)这瓶有毒。但仔细一想,我们发现\([1,n)\)的瓶子中任意一个我们分出的区间\([l,r]\),都用去了\(......
  • 计算机微机
    计算机微机结构通常指的是微型计算机的内部结构,包括硬件和它们之间的互连方式。微机结构涉及到计算机组成原理,是计算机科学与技术领域的基础知识之一。下面简要介绍微机结构的主要组成部分:中央处理器(CPU):是计算机的核心,负责解释和执行程序指令。它包括控制单元(CU)和算术逻辑单元(AL......
  • take a risk
    "Takearisk"isanEnglishidiomthatmeanstodosomethingthatcouldpotentiallyhavenegativeconsequences,butwhichalsohasthepotentialforpositiverewards.Itisoftenusedtoencouragepeopletostepoutsideoftheircomfortzonesan......
  • 计算机操作系统
    计算机操作系统是管理计算机硬件与软件资源的系统软件,它是计算机系统的核心与基石。操作系统负责控制和协调计算机及其外部设备之间的操作,同时也为用户和应用程序提供了一个交互的界面。操作系统的主要功能包括:资源管理:操作系统负责高效地管理计算机的硬件资源,如CPU、内存、输入......
  • 微机结构总结
    通过对微机结构的学习,我对微机有了更加全面的了解。微机,又称为“微型计算机”,是相对于大型计算机而言的。它以微处理器为核心,配合内存、输入输出接口电路和相应的辅助电路而构成的裸机。下面是他的结构组成:中央处理器(CPU):CPU是微机的核心部件,它负责执行程序中的指令,完成各种算术......
  • 机器学习Scikit-learn库概要
    Scikit-learn(简称为sklearn)是一个开源的Python机器学习库,提供了丰富而强大的工具,用于数据挖掘和数据分析。它的发展始于2007年,由DavidCournapeau在GoogleSummerofCode项目中启动,后续得到了许多开发者的贡献,包括法国国家信息与自动化研究所(INRIA)、Waikato大学等机构。Scikit-le......
  • 操作系统
    操作系统是管理计算机硬件与软件资源的系统软件,它是计算机系统的核心组成部分。操作系统主要具有进程管理、内存管理、文件系统管理、设备管理、提供用户接口功能。不同的操作系统具有各自的特点和适用场景,它们共同推动着计算机技术的不断发展。操作系统是管理计算机硬件与软件资......
  • pycnblog的使用
    功能一键拖拽上传默认“未发布”,可选择直接发布重复上传,提示是否更新博客环境python3是需要python环境的,python的安装自己去百度一下pycnblog的使用[email protected]:dongfanger/pycnblog.gitpipinstallpyyaml注意博客园6.21更新,MetaWeblog现在不支持密......
  • 使用 __get__ 向已有类实例注入函数
    突然有这样的特殊需求:向已经实例化的类对象添加新方法。例如,我的model本没有实现predict_step方法,现在我想向model注入这个函数:defpredict_step(self,batch,batch_idx,dataloader_idx=0):logits=self(**batch)["logits"]pred=F.softmax(logits,dim=-1)......