using Cysharp.Threading.Tasks; using System; using System.Collections; using System.Collections.Generic; using System.Threading.Tasks; using UnityEngine; using UnityEngine.SceneManagement; namespace TFramework { public class ResourceManager : BaseManager { /// /// 所有AssetBundle资源包清单 /// public AssetBundleManifest AssetBundleManifest { get; private set; } /// /// 缓存的所有AssetBundle包【AB包名称、AB包】 /// public Dictionary AssetBundles { get; private set; } = new Dictionary(); /// /// 当前激活的场景 /// public Scene CurrentScene { get; private set; } public void Awake() { CurrentScene= SceneManager.GetActiveScene(); } public T LoadAsset(LoadResHandle resHandle) where T : UnityEngine.Object { return LoadAsset(resHandle.ResourcePath, resHandle.AssetPath, resHandle.AssetBundleName, resHandle.LoadMode); } /// /// 同步加载资源 /// /// /// /// /// /// /// public T LoadAsset(string resPath, string assetPath, string assetBundleName = "", ResLoadMode resLoadMode = ResLoadMode.Resourece) where T : UnityEngine.Object { if (resLoadMode == ResLoadMode.Resourece) return Resources.Load(resPath); else { #if UNITY_EDITOR if (AssetConfig.RuntimeMode == UpdateMode.Editor) return UnityEditor.AssetDatabase.LoadAssetAtPath(assetPath); #endif assetBundleName = assetBundleName.ToLower(); if (AssetBundleManifest == null) { if (!AssetBundles.ContainsKey(AssetConfig.AssetBundleManifestName)) AssetBundles.Add(AssetConfig.AssetBundleManifestName, AssetBundle.LoadFromFile(AssetConfig.AssetBundleRootPath + AssetConfig.AssetBundleManifestName)); AssetBundleManifest = AssetBundles[AssetConfig.AssetBundleManifestName].LoadAsset("AssetBundleManifest"); } string[] dependencies = AssetBundleManifest.GetAllDependencies(assetBundleName); for (int i = 0; i < dependencies.Length; i++) { if (!AssetBundles.ContainsKey(dependencies[i])) AssetBundles.Add(dependencies[i], AssetBundle.LoadFromFile(AssetConfig.AssetBundleRootPath + dependencies[i])); } if (!AssetBundles.ContainsKey(assetBundleName)) AssetBundles.Add(assetBundleName, AssetBundle.LoadFromFile(AssetConfig.AssetBundleRootPath + assetBundleName)); return AssetBundles[assetBundleName].LoadAsset(assetPath); } } /// /// 同步加载Resources下的资源 /// /// 资源类型 /// 资源路径 /// public T LoadAsset(string resPath) where T : UnityEngine.Object => LoadAsset(resPath, "", ""); /// /// 同步加载AssetBundle资源 /// /// 资源类型 /// 资源路径 /// AB包名 /// public T LoadAsset(string assetPath, string assetBundleName) where T : UnityEngine.Object => LoadAsset("", assetPath, assetBundleName, ResLoadMode.AssetBundle); /// /// 异步加载资源 /// /// 资源类型 /// 资源路径 /// 加载中事件 /// 加载完成事件 /// public async UniTask LoadAssetAsync(LoadResHandle resHandle) where T : UnityEngine.Object { return await LoadAsync(resHandle); } private async UniTask LoadAsync(LoadResHandle resHandle) where T : UnityEngine.Object { UnityEngine.Object asset = null; if (resHandle.LoadMode == ResLoadMode.Resourece) { ResourceRequest request = Resources.LoadAsync(resHandle.ResourcePath); await request.ToUniTask(Progress.Create(pro => { resHandle.OnLoading?.Invoke(pro); })); if (!request.asset) throw new UnityException($"资源加载失败:Resources文件夹中不存在资源 {resHandle.ResourcePath}!"); else asset = request.asset; } else { #if UNITY_EDITOR if (AssetConfig.RuntimeMode == UpdateMode.Editor) { resHandle.OnLoading?.Invoke(1); asset = UnityEditor.AssetDatabase.LoadAssetAtPath(resHandle.AssetPath); if (asset) asset = asset as T; else throw new UnityException($"加载资源失败:路径{resHandle.AssetPath}中不存在资源 {resHandle.AssetPath}!"); } else { //等待相关依赖资源的加载 await LoadDependenciesAssetBundleAsync(resHandle.AssetBundleName.ToLower()); await LoadAssetBundleAsync(resHandle.AssetBundleName.ToLower(), resHandle.OnLoading); if (AssetBundles.ContainsKey(resHandle.AssetBundleName.ToLower())) { //asset = AssetBundles[resHandle.AssetBundleName].LoadAsset(resHandle.AssetPath); AssetBundleRequest request = AssetBundles[resHandle.AssetBundleName.ToLower()].LoadAssetAsync(resHandle.AssetPath); await request; await request.ToUniTask(Progress.Create(pro => { resHandle.OnLoading?.Invoke(pro); })); asset = request.asset; if (!asset) throw new UnityException(string.Format("加载资源失败:AB包 {0} 中不存在资源 {1}!", resHandle.AssetBundleName, resHandle.AssetPath)); } } #else await LoadDependenciesAssetBundleAsync(resHandle.AssetBundleName.ToLower()); await LoadAssetBundleAsync(resHandle.AssetBundleName.ToLower(), resHandle.OnLoading); if (AssetBundles.ContainsKey(resHandle.AssetBundleName.ToLower())) { AssetBundleRequest request = AssetBundles[resHandle.AssetBundleName.ToLower()].LoadAssetAsync(resHandle.AssetPath); await request; await request.ToUniTask(Progress.Create(pro => { resHandle.OnLoading?.Invoke(pro); })); asset = request.asset; if (!asset) throw new UnityException(string.Format("加载资源失败:AB包 {0} 中不存在资源 {1}!", resHandle.AssetBundleName, resHandle.AssetPath)); } #endif } if (asset) { resHandle.OnLoadOver?.Invoke(asset as T); } else resHandle.OnLoadOver?.Invoke(null); return asset as T; } /// /// 异步加载场景(Resource模式) /// /// 场景路径 /// 加载中事件 /// 加载完成事件 /// public async UniTask LoadSceneAsync(string scenePath, TAction OnLoading, TFuncAsync OnLoadOver, LoadSceneMode loadSceneMode = LoadSceneMode.Single) { return await LoadScene(scenePath, ResLoadMode.Resourece, "", OnLoading, OnLoadOver, loadSceneMode); } /// /// 异步加载场景 /// /// 场景路径 /// 加载中事件 /// 加载完成事件 /// public async UniTask LoadSceneAsync(LoadResHandle resHandle, LoadSceneMode loadSceneMode = LoadSceneMode.Single) { return await LoadScene(resHandle.AssetPath,resHandle.LoadMode,resHandle.AssetBundleName,resHandle.OnLoading,resHandle.OnLoadOver, loadSceneMode); } private async UniTask LoadScene(string scenePath, ResLoadMode loadMode ,string assetBundleName ,TAction OnLoading,TFuncAsync OnLoadOver, LoadSceneMode loadSceneMode) { if (SceneManager.GetSceneByPath(scenePath) == CurrentScene) { Debug.LogWarning($"场景{scenePath}已加载!"); return CurrentScene; } AsyncOperation ao; if (loadMode == ResLoadMode.Resourece) { ao = SceneManager.LoadSceneAsync(scenePath, loadSceneMode); } else { await LoadDependenciesAssetBundleAsync(assetBundleName.ToLower()); #if UNITY_EDITOR if (AssetConfig.RuntimeMode == UpdateMode.Editor) { LoadSceneParameters parameters = new LoadSceneParameters() { loadSceneMode = LoadSceneMode.Single, localPhysicsMode = LocalPhysicsMode.None }; ao = UnityEditor.SceneManagement.EditorSceneManager.LoadSceneAsyncInPlayMode(scenePath, parameters); } else { await LoadAssetBundleAsync(assetBundleName.ToLower(), OnLoading); ao = SceneManager.LoadSceneAsync(scenePath, loadSceneMode); } #else await LoadAssetBundleAsync(assetBundleName, OnLoading); ao = SceneManager.LoadSceneAsync(scenePath, loadSceneMode); #endif } ao.allowSceneActivation = false; while (ao.progress < 0.9f) { OnLoading?.Invoke(ao.progress); await UniTask.Yield(); } Debug.Log($"加载场景{scenePath}完成"); OnLoading?.Invoke(1); if(OnLoadOver != null) { if (await OnLoadOver.Invoke(SceneManager.GetSceneByPath(scenePath))) { ao.allowSceneActivation = true; } } else ao.allowSceneActivation = true; await ao.ToUniTask(); SceneManager.SetActiveScene(SceneManager.GetSceneByPath(scenePath)); CurrentScene = SceneManager.GetActiveScene(); return CurrentScene; } /// /// 异步清理内存 回收垃圾 /// /// public async UniTask ClearMemoryAsync() { await ClearMemory(); } /// /// 清理内存,释放空闲内存(异步) /// /// 协程迭代器 private async UniTask ClearMemory() { await Resources.UnloadUnusedAssets(); GC.Collect(); GC.WaitForPendingFinalizers(); } /// /// 异步卸载资源 /// /// public async UniTask UnLoadAsstAsync(ResLoadMode resLoadMode, string assetBundleName, bool unloadAllLoadedObjects = false) { await UnLoadAsst(resLoadMode, assetBundleName, unloadAllLoadedObjects); } private async UniTask UnLoadAsst(ResLoadMode resLoadMode, string assetBundleName, bool unloadAllLoadedObjects = false) { await UnLoadAsset(ResLoadMode.Resourece, assetBundleName, unloadAllLoadedObjects); } /// /// 异步卸载场景 /// /// /// public async UniTask UnloadSceneAsync(Scene scene, TAction OnUnloading = null, TAction OnUnloadOver = null) { Debug.Log($"卸载场景{scene.name}"); await UnloadScene(scene, OnUnloading, OnUnloadOver); } private async UniTask UnloadScene(Scene scene, TAction OnUnloading, TAction OnUnloadOver) { AsyncOperation ao = SceneManager.UnloadSceneAsync(scene); while (!ao.isDone) { OnUnloading?.Invoke(ao.progress); await UniTask.Yield(); } OnUnloadOver?.Invoke(); CurrentScene = SceneManager.GetActiveScene(); } public async UniTask UnLoadAsset(ResLoadMode resLoadMode, string assetBundleName, bool unloadAllLoadedObjects = false) { if (resLoadMode == ResLoadMode.Resourece) { await Resources.UnloadUnusedAssets(); } else { assetBundleName = assetBundleName.ToLower(); if (AssetBundles.ContainsKey(assetBundleName)) { AssetBundles[assetBundleName].Unload(unloadAllLoadedObjects); AssetBundles.Remove(assetBundleName); } await UniTask.Yield(); } } public async UniTask UnLoadAllABAssetAsync(bool unloadAllLoadedObjects = false) { List keys = new List(AssetBundles.Keys); for (int i = 0; i < keys.Count; i++) { Debug.Log($"卸载AB包{keys[i]}"); await AssetBundles[keys[i]].UnloadAsync(unloadAllLoadedObjects); AssetBundles.Remove(keys[i]); } } /// /// 异步加载AB包清单 /// /// 协程迭代器 private async UniTask LoadAssetBundleManifestAsync() { if (string.IsNullOrEmpty(AssetConfig.AssetBundleManifestName)) { throw new UnityException("请设置资源配置文件的 AssetBundleManifestName 属性,为所有AB包提供依赖清单!"); } else { if (AssetBundleManifest == null) { await LoadAssetBundleAsync(AssetConfig.AssetBundleManifestName, null); if (AssetBundles.ContainsKey(AssetConfig.AssetBundleManifestName)) { AssetBundleManifest = AssetBundles[AssetConfig.AssetBundleManifestName].LoadAsset("AssetBundleManifest"); await UnLoadAsset(ResLoadMode.AssetBundle, AssetConfig.AssetBundleManifestName); } } } } /// /// 异步加载AB包(提供进度回调) /// /// AB包名称 /// 加载中事件 /// 是否是加载清单 /// 协程迭代器 private async UniTask LoadAssetBundleAsync(string assetBundleName, TAction onLoading) { if (!AssetBundles.ContainsKey(assetBundleName)) { AssetBundleCreateRequest abRequst = AssetBundle.LoadFromFileAsync(AssetConfig.AssetBundleRootPath + assetBundleName); await abRequst; while (!abRequst.isDone) { onLoading?.Invoke(abRequst.progress / 2); await UniTask.Yield(); } if (abRequst.assetBundle) AssetBundles.Add(assetBundleName, abRequst.assetBundle); else throw new UnityException($" 未加载到AB包【{assetBundleName}】!"); } onLoading?.Invoke(1); } /// /// 异步加载依赖AB包 /// /// AB包名称 /// 协程迭代器 private async UniTask LoadDependenciesAssetBundleAsync(string assetBundleName) { #if UNITY_EDITOR if (AssetConfig.RuntimeMode != UpdateMode.Editor) { await LoadAssetBundleManifestAsync(); if (AssetBundleManifest != null) { string[] dependencies = AssetBundleManifest.GetAllDependencies(assetBundleName); foreach (string item in dependencies) { if (AssetBundles.ContainsKey(item)) continue; await LoadAssetBundleAsync(item, null); } } } #else await LoadAssetBundleManifestAsync(); if (AssetBundleManifest != null) { string[] dependencies = AssetBundleManifest.GetAllDependencies(assetBundleName); foreach (string item in dependencies) { if (AssetBundles.ContainsKey(item)) continue; await LoadAssetBundleAsync(item, null); } } #endif } } }