【Unity】AssetBundle_Manager_(AssetBundle管理器)
GItHub链接https://github.com/BuZhiZhaoXi-Fly/Unity_Managers_.git
using System;using System.Collections;using System.Collections.Generic;using System.IO;using System.Threading.Tasks;using UnityEngine;using UnityEngine.Events;/// /// AB包管理器/// public class AssetBundle_Manager_ : SingletonAutoMono{ #region 变量 private Dictionary abDic = new();//用于管理AB的容器 private Dictionary objDic = new();//用于存储被加载资源的容器 private AssetBundle abMain = null;//主包 private AssetBundleManifest abMainManifest = null;//主包依赖 private string abPath = Application.streamingAssetsPath;//AB包文件夹路径 public string ABPath { set => abPath = value; get => abPath; } //主包名称,这里可以根据实际情况修改主包名称 private string ABMainName { get {#if UNITY_IOS return \"IOS\";#elif UNITY_ANDROID return \"Android\";#else return \"AB Package\";#endif } } #endregion #region 同步加载AB包 /// /// 加载主包以及主包配置文件 /// private bool LoadMainAB() { //加载主包 if (abMain == null) { //尝试加载AB包 string path = Path.Combine(ABPath, ABMainName); abMain = AssetBundle.LoadFromFile(path); //如果加载失败 则输出错误信息 if (abMain == null) { Debug.LogError($\"主包加载失败!路径:{path}\"); return false; } } //加载主包的依赖配置文件 if (abMainManifest == null) { //尝试加载主包的AssetBundleManifest abMainManifest = abMain.LoadAsset(\"AssetBundleManifest\"); //如果加载失败 则输出错误信息 if (abMainManifest == null) { Debug.LogError(\"主包的AssetBundleManifest加载失败!\"); return false; } } //如果主包和主包配置文件都加载成功 则返回true return true; } /// /// 加载目标包 /// /// 目标包名称 private AssetBundle LoadTargetAB(string targetABName) { //如果主包和主包配置文件没有加载成功 则返回null if (!LoadMainAB()) { Debug.LogError(\"主包加载失败,无法加载目标包\"); return null; } //获取所有依赖的名称 string[] dependenciesStrs = abMainManifest.GetAllDependencies(targetABName); //加载所有依赖 foreach (string dependencyStr in dependenciesStrs) { //如果依赖包没有加载过 则加载依赖包 if (!abDic.ContainsKey(dependencyStr)) { //尝试加载依赖包 var dependencyAB = AssetBundle.LoadFromFile(Path.Combine(ABPath, dependencyStr)); //如果加载失败 则输出错误信息 if (dependencyAB == null) { Debug.LogError($\"依赖包加载失败!路径:{Path.Combine(ABPath, dependencyStr)}\"); continue; } //将加载的依赖包存入字典 abDic.TryAdd(dependencyStr, dependencyAB); } } //加载目标AB包 //如果目标AB包没有加载过 则加载目标AB包 if (!abDic.TryGetValue(targetABName, out var targetAB)) { targetAB = AssetBundle.LoadFromFile(Path.Combine(ABPath, targetABName)); //如果加载失败 则输出错误信息 if (targetAB == null) { Debug.LogError($\"目标AB包加载失败!路径:{Path.Combine(ABPath, targetABName)}\"); return null; } //将加载的目标AB包存入字典 abDic.TryAdd(targetABName, targetAB); } //返回加载的目标AB包 return targetAB; } /// /// 生成资源Key /// /// AB包 /// 资源包 /// 后缀 /// 资源Key private string GenerateObjKey(string abName, string resName, string suffix = \"\") { return $\"{abName}_{resName}_{suffix}_\"; } /// /// 加载资源的接口 /// /// 目标资源Key /// 目标AB包 /// 目标资源名称 /// 回调函数 /// 目标资源 private UnityEngine.Object LoadResInternal(string objKey, string targetABName, string targetResName,Func callBack) { //如果资源容器中没有该资源 if (!objDic.TryGetValue(objKey, out UnityEngine.Object obj) || obj == null) { //则加载目标AB包 AssetBundle ab = LoadTargetAB(targetABName); //如果加载失败 则返回null if (ab == null) { Debug.LogError($\"目标AB包加载失败:{targetABName}\"); return null; } //加载目标资源 obj = callBack(ab); //如果加载失败 则输出错误信息 if (obj == null) { Debug.LogError($\"资源加载失败:AB包:{targetABName},资源名:{targetResName}\"); return null; } else { //将加载的资源存入字典 objDic[objKey] = obj; } } return obj; } /// /// 同步加载资源(以名称的形式加载资源) /// /// 目标包 /// 目标资源 /// 资源 public UnityEngine.Object LoadABRes(string targetABName, string targetResName) { // 资源容器中存储的资源名称 string objKey = GenerateObjKey(targetABName, targetResName, \"Name\"); // 获取资源 return LoadResInternal(objKey, targetABName, targetResName, (ab) => ab.LoadAsset(targetResName)); } /// /// 同步加载资源(以Type的形式加载资源) /// /// 目标AB包名称 /// 目标资源名称 /// 目标资源类型 /// 资源 public UnityEngine.Object LoadABRes(string targetABName, string targetResName, System.Type type) { // 资源容器中存储的资源名称 string objKey = GenerateObjKey(targetABName, targetResName, \"Type\"); // 获取资源 return LoadResInternal(objKey, targetABName, targetResName, (ab) => ab.LoadAsset(targetResName, type)); } /// /// 同步加载资源(以泛型加载资源) /// /// 目标资源的类型(泛型) /// 目标AB包名称 /// 目标资源名称 /// 资源 public T LoadABRes(string targetABName, string targetResName) where T : UnityEngine.Object { // 资源容器中存储的资源名称 string objKey = GenerateObjKey(targetABName, targetResName, \"Generics\"); // 获取资源 return LoadResInternal(objKey, targetABName, targetResName, (ab) => ab.LoadAsset(targetResName)) as T; } #endregion #region 异步加载AB包 /// /// 用于将带回调的协程包装成 Task /// private Task WrapCoroutine(Func<UnityAction, string, IEnumerator> coroutineStarter, string path = null) { var tcs = new TaskCompletionSource(); StartCoroutine(coroutineStarter((result) => tcs.SetResult(result), path)); return tcs.Task; } /// /// 加载主包以及主包配置文件 /// private IEnumerator LoadMainABAsyncCor(UnityAction tcsCallBack = null, string path = null) { //加载主包 if (abMain == null) { //尝试加载AB包 AssetBundleCreateRequest abcr = AssetBundle.LoadFromFileAsync(path); //等待AssetBundleCreateRequest完成 yield return abcr; //如果加载失败 则输出错误信息 if (abcr.assetBundle == null) { Debug.LogError($\"AssetBundleCreateRequest加载失败!\"); yield break; } //获取加载的主包 abMain = abcr.assetBundle; } //加载主包的依赖配置文件 if (abMainManifest == null) { //尝试加载主包的AssetBundleManifest AssetBundleRequest abr = abMain.LoadAssetAsync(\"AssetBundleManifest\"); yield return abr; if (abr.asset == null) { Debug.LogError(\"AssetBundleRequest加载失败!\"); yield break; } abMainManifest = abr.asset as AssetBundleManifest; } //如果主包和主包配置文件都加载成功 则执行回调函数 tcsCallBack?.Invoke(abMain); } /// /// 异步加载目标AB包的协程 /// /// 回调函数 /// 目标AB包 /// private IEnumerator LoadFromFileAsyncCor(UnityAction callBack = null, string targetABName = null) { //加载目标AB包 AssetBundleCreateRequest abcr = AssetBundle.LoadFromFileAsync(targetABName); //等待AssetBundle加载完成 yield return abcr; //如果加载失败 则输出错误信息 if (abcr.assetBundle == null) { Debug.LogError($\"目标AssetBundleCreateRequest加载失败!\"); yield break; } //获取加载的AssetBundle AssetBundle ab = abcr.assetBundle; //如果有回调函数 则执行回调 callBack?.Invoke(ab); } /// /// 异步加载目标AB包 /// /// 目标AB包名称 private async Task LoadTargetABAsync(string targetABName) { await WrapCoroutine(LoadMainABAsyncCor, Path.Combine(ABPath, ABMainName)); //获取所有依赖的名称 string[] dependenciesStrs = abMainManifest.GetAllDependencies(targetABName); //加载所有依赖 foreach (string dependencyStr in dependenciesStrs) { if (!abDic.ContainsKey(dependencyStr)) { //尝试加载依赖包 var denpendencyAB = await WrapCoroutine(LoadFromFileAsyncCor, Path.Combine(ABPath, dependencyStr)); //如果加载失败 则输出错误信息 if (denpendencyAB == null) { Debug.LogError($\"依赖包加载失败!路径:{Path.Combine(ABPath, dependencyStr)}\"); continue; } //将加载的依赖包存入字典 abDic.TryAdd(dependencyStr, denpendencyAB); } } //加载目标AB包 if (!abDic.TryGetValue(targetABName, out AssetBundle ab) || ab == null) { string path = Path.Combine(ABPath, targetABName); ab = await WrapCoroutine(LoadFromFileAsyncCor, path); //如果加载失败 则输出错误信息 if (ab == null) { Debug.LogError($\"目标AB包加载失败!路径:{path}\"); return null; } //将加载的目标AB包存入字典 abDic.TryAdd(targetABName, ab); } //返回加载的目标AB包 return ab; } /// /// 用于封装异步加载资源的通用方法 /// /// 泛型 /// 目标AB包名称 /// 目标资源名称 /// 资源存储的Key /// 回调函数 /// 加载资源的委托 /// 对应类型的资源 private async Task AwaitAssetBundleRequest(string targetABName, string targetResName, string objKey, UnityAction callBack, Func loadRequestGetter) where T : UnityEngine.Object { //如果资源容器中已经有该资源 则执行回调并返回资源 if (objDic.TryGetValue(objKey, out UnityEngine.Object obj)) { callBack?.Invoke(obj); return obj as T; } //异步加载目标AB包 AssetBundle ab = await LoadTargetABAsync(targetABName); //判断callBack2是否为null if (loadRequestGetter == null) { Debug.LogError(\"加载函数 callBack2 为空!\"); return null; } AssetBundleRequest abr = loadRequestGetter.Invoke(ab, targetResName); //等待AssetBundleRequest完成 while (!abr.isDone) { await Task.Yield(); } //判断加载的资源是否为null if (abr.asset == null) { Debug.LogError(\"AssetBundleRequest加载失败!(资源为空)\"); return null; } obj = abr.asset; //如果有回调函数 则执行回调wo1 callBack?.Invoke(obj); //将加载的资源存入字典 objDic[objKey] = obj; return abr.asset as T; } /// /// 异步加载资源(以名称的形式加载资源) /// /// 目标AB包 /// 目标资源 /// 对应类型的资源 public async Task LoadABResAsync(string targetABName, string targetResName, UnityAction callBack) { //生成资源Key string objKey = GenerateObjKey(targetABName, targetResName, \"Name\"); UnityEngine.Object obj = await AwaitAssetBundleRequest(targetABName, targetResName, objKey, callBack, (ab, targetResName) => ab.LoadAssetAsync(targetResName)); //返回资源 return obj; } /// /// 异步加载资源(以Type的形式加载资源) /// /// 目标AB包 /// 目标资源 /// 目标资源类型 /// 对应类型的资源 public async Task LoadABResAsync(string targetABName, string targetResName, System.Type type, UnityAction callBack) { //生成资源Key string objKey = GenerateObjKey(targetABName, targetResName, \"Type\"); UnityEngine.Object obj = await AwaitAssetBundleRequest(targetABName, targetResName, objKey, callBack, (ab, targetResName) => ab.LoadAssetAsync(targetResName, type)); //返回资源 return obj; } /// /// 异步加载资源(以泛型加载资源) /// /// 泛型 /// 目标AB包 /// 目标资源 /// 目标类型 /// 对应类型的资源 public async Task LoadABResAsync(string targetABName, string targetResName, UnityAction callBack) where T : UnityEngine.Object { //生成资源Key string objKey = GenerateObjKey(targetABName, targetResName, \"Generics\"); T obj = await AwaitAssetBundleRequest(targetABName, targetResName, objKey, callBack, (ab, targetResName) => ab.LoadAssetAsync(targetResName)); //返回资源 return obj; } #endregion #region 同步卸载AB包 /// /// 单个包卸载 /// /// 目标包名称 public void UnLoadAB(string targetABName) { if(abDic.ContainsKey(targetABName)) { abDic[targetABName].Unload(false); abDic.Remove(targetABName); } } /// /// 所有包卸载 /// public void UnLoadAllAB() { //卸载所有AB包 foreach (var ab in abDic) { ab.Value.Unload(false); } abDic.Clear(); // 卸载主包和主包配置文件 if (abMain != null) { abMain.Unload(false); abMain = null; } if (abMainManifest != null) { abMainManifest = null; } } #endregion #region 异步卸载AB包 /// /// 异步卸载AB包的协程 /// /// 目标AB包名称 /// 回调函数 /// 协程 private IEnumerator UnLoadABAsyncCor(string targetABName, UnityAction callBack) { //先在字典中查找目标AB包 if (abDic.ContainsKey(targetABName)) { //等待一帧以确保资源加载完成 yield return null; //卸载目标AB包 abDic[targetABName].Unload(false); //从字典中移除目标AB包 bool isSuccess = abDic.Remove(targetABName); //执行回调函数 callBack?.Invoke(isSuccess); } } /// /// 异步卸载AB包 /// /// 目标包名称 /// 回调函数 /// 是否成功卸载AB包 public Task UnLoadABAsync(string targetABName, UnityAction callBack = null) { //使用TaskCompletionSource来封装异步操作 var tcs = new TaskCompletionSource(); //开始协程卸载AB包 StartCoroutine(UnLoadABAsyncCor(targetABName, (b) => { tcs.SetResult(b); })); //执行回调函数 callBack?.Invoke(); //返回一个Task对象来判断当前协程是否完成 return tcs.Task; } /// /// 清空所有AB包的协程 /// /// 回调函数 /// 协程 private IEnumerator UnLoadAllABAsyncCor(UnityAction callBack) { //卸载内存中所有的AB包 AssetBundle.UnloadAllAssetBundles(false); //清空字典 abDic.Clear(); //执行回调函数 callBack?.Invoke(true); //等待一帧以确保资源加载完成 yield return null; } /// /// 删除所有AB包的异步方法 /// /// 回调函数 /// 是否成功卸载资源 public Task UnLoadAllABAsync(UnityAction callBack = null) { //使用TaskCompletionSource来封装异步操作 var tcs = new TaskCompletionSource(); //开始协程卸载所有AB包 StartCoroutine(UnLoadAllABAsyncCor( (b) => { tcs.SetResult(b); })); //执行回调函数 callBack?.Invoke(); return tcs.Task; } /// /// 清理objDic里的缓存资源 /// public void ClearUnusedObjects() { List toRemove = new List(); foreach (var kvp in objDic) { if (kvp.Value == null) toRemove.Add(kvp.Key); } foreach (var key in toRemove) { objDic.Remove(key); } } #endregion #region objDic相关操作 /// /// 清空objDic里的缓存资源 /// public void ClearObjDic() { if (objDic.Count > 0) { objDic.Clear(); } } #endregion}