合集 - Unity学习笔记(13)1.Unity学习笔记–基础2023-11-012.Unity学习笔记–入门2023-10-293.Unity学习笔记–数据持久化之PlayerPrefs的使用2023-11-194.Unity学习笔记–数据持久化XML文件(1)2023-11-205.Unity学习笔记–数据持久化XML文件(2)2023-12-016.Unity学习笔记–数据持久化Json2023-12-03:西部世界move加速器7.NGUI学习笔记(1)03-018.NGUI学习笔记203-039.NGUI学习笔记3.503-0510.NGUI学习笔记4.003-0611.Unity 热更–AssetBundle学习笔记 0.705-0112.Unity 热更–AssetBundle学习笔记 0.805-0213.Unity 热更–AssetBundle学习笔记 1.0【AB包资源加载工具类的实现】05-03收起
工具类封装
通过上文中对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 |
| | { |
| | /// |
| | /// 加载AssetBundle工具类 单例 |
| | /// |
| | public class LoadAssetBundleManager: SingletonAutoMono |
| | { |
| | //主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 |
| | } |
| | } |
| | |
| | /// |
| | /// 根据名称加载AB包 也会检查相关依赖包 进行加载 |
| | /// |
| | /// AB包的名称 |
| | 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"); |
| | } |
| | //加载目标资源包的依赖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); |
| | } |
| | } |
| | } |
| | |
| | /// |
| | /// 从AB包中获取具体资源 |
| | /// |
| | /// AB包名称 |
| | /// 资源名称 |
| | /// Object资源 |
| | public Object LoadResource(string abName, string resName) |
| | { |
| | LoadAssetBundle(abName); |
| | Object resObj = null; |
| | resObj = assetBundlesDic[abName].LoadAsset(resName); |
| | return resObj; |
| | } |
| | /// |
| | /// 泛型方法重载 |
| | /// |
| | public T LoadResource(string abName, string resName) where T:Object |
| | { |
| | LoadAssetBundle(abName); |
| | T res = assetBundlesDic[abName].LoadAsset(resName); |
| | return res; |
| | } |
| | /// |
| | /// 根据资源类型重载方法 |
| | /// |
| | 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 callback) |
| | { |
| | StartCoroutine(LoadResourceIEn(abName, resName, callback)); |
| | } |
| | //异步加载协程 |
| | private IEnumerator LoadResourceIEn(string abName, string resName, UnityAction callback) |
| | { |
| | LoadAssetBundle(abName); |
| | AssetBundleRequest request = assetBundlesDic[abName].LoadAssetAsync(resName); |
| | yield return request; |
| | callback(request.asset); |
| | } |
| | //根据泛型来异步加资源 |
| | public void LoadResourceAsync(string abName, string resName, UnityAction callback) where T : Object |
| | { |
| | StartCoroutine(LoadResourceIEn(abName, resName, callback)); |
| | } |
| | //异步加载协程 |
| | private IEnumerator LoadResourceIEn(string abName, string resName, UnityAction callback) where T :Object |
| | { |
| | LoadAssetBundle(abName); |
| | AssetBundleRequest request = assetBundlesDic[abName].LoadAssetAsync(resName); |
| | yield return request; |
| | callback(request.asset); |
| | } |
| | //根据res类型异步加载资源 |
| | //根据泛型来异步加资源 |
| | public void LoadResourceAsync(string abName, string resName, System.Type type,UnityAction callback) |
| | { |
| | StartCoroutine(LoadResourceIEn(abName, resName, type, callback)); |
| | } |
| | //异步加载协程 |
| | private IEnumerator LoadResourceIEn(string abName, string resName, System.Type type, UnityAction 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(); |
| | } |
| | 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("model", "cube"); |
| | cube2.transform.position = Vector3.left; |
| | Instantiate(cube2); |
| | |
| | |
| | LoadAssetBundleManager.Instance().LoadResourceAsync("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(); |