Unity 热更--AssetBundle学习笔记 1.0【AB包资源加载工具类的实现】
工具类封装
通过上文中对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();
本文作者:畅知
本文链接:https://www.cnblogs.com/TonyCode/p/18170759
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业