using System; using System.Collections; using System.Collections.Generic; 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 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 Coroutine LoadAssetAsync(LoadResHandle resHandle) where T : UnityEngine.Object { return StartCoroutine(LoadAsync(resHandle)); } private IEnumerator LoadAsync(LoadResHandle resHandle) where T : UnityEngine.Object { UnityEngine.Object asset = null; if (resHandle.LoadMode == ResLoadMode.Resourece) { ResourceRequest request = Resources.LoadAsync(resHandle.ResourcePath); while (!request.isDone) { resHandle.OnLoading?.Invoke(request.progress); yield return null; } resHandle.OnLoading?.Invoke(1); 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 { //等待相关依赖资源的加载 yield return LoadDependenciesAssetBundleAsync(resHandle.AssetBundleName); yield return LoadAssetBundleAsync(resHandle.AssetBundleName, resHandle.OnLoading); if (AssetBundles.ContainsKey(resHandle.AssetBundleName.ToLower())) { //asset = AssetBundles[resHandle.AssetBundleName].LoadAsset(resHandle.AssetPath); AssetBundleRequest request = AssetBundles[resHandle.AssetBundleName.ToLower()].LoadAssetAsync(resHandle.AssetPath); yield return request; while (!request.isDone) { resHandle.OnLoading(request.progress / 2 + 0.5f); yield return null; } asset = request.asset; if (!asset) throw new UnityException(string.Format("加载资源失败:AB包 {0} 中不存在资源 {1}!", resHandle.AssetBundleName, resHandle.AssetPath)); } } #else yield return LoadDependenciesAssetBundleAsync(resHandle.AssetBundleName); yield return LoadAssetBundleAsync(resHandle.AssetBundleName, resHandle.OnLoading); if (AssetBundles.ContainsKey(resHandle.AssetBundleName.ToLower())) { AssetBundleRequest request = AssetBundles[resHandle.AssetBundleName.ToLower()].LoadAssetAsync(resHandle.AssetPath); yield return request; while(!request.isDone) { resHandle.OnLoading(request.progress / 2+0.5f); yield return null; } 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); } /// /// 异步加载场景(Resource模式) /// /// 场景路径 /// 加载中事件 /// 加载完成事件 /// public Coroutine LoadSceneAsync(string scenePath, TAction OnLoading, TAction OnLoadOver, LoadSceneMode loadSceneMode = LoadSceneMode.Single) { return StartCoroutine(LoadScene(scenePath, ResLoadMode.Resourece, "", OnLoading, OnLoadOver, loadSceneMode)); } /// /// 异步加载场景 /// /// 场景路径 /// 加载中事件 /// 加载完成事件 /// public Coroutine LoadSceneAsync(LoadResHandle resHandle, LoadSceneMode loadSceneMode = LoadSceneMode.Single) { return StartCoroutine(LoadScene(resHandle.AssetPath,resHandle.LoadMode,resHandle.AssetBundleName,resHandle.OnLoading,resHandle.OnLoadOver, loadSceneMode)); } private IEnumerator LoadScene(string scenePath, ResLoadMode loadMode ,string assetBundleName ,TAction OnLoading,TAction OnLoadOver, LoadSceneMode loadSceneMode) { if (SceneManager.GetSceneByPath(scenePath) == CurrentScene) { Debug.LogWarning($"场景{scenePath}已加载!"); yield break; } if (loadMode == ResLoadMode.Resourece) { AsyncOperation ao = SceneManager.LoadSceneAsync(scenePath, loadSceneMode); while (!ao.isDone) { OnLoading?.Invoke(ao.progress); yield return null; } } else { yield return LoadDependenciesAssetBundleAsync(assetBundleName); #if UNITY_EDITOR if (AssetConfig.RuntimeMode == UpdateMode.Editor) { LoadSceneParameters parameters = new LoadSceneParameters() { loadSceneMode = LoadSceneMode.Single, localPhysicsMode = LocalPhysicsMode.None }; AsyncOperation ao = UnityEditor.SceneManagement.EditorSceneManager.LoadSceneAsyncInPlayMode(scenePath, parameters); while (!ao.isDone) { OnLoading?.Invoke(ao.progress); yield return null; } } else { yield return LoadAssetBundleAsync(assetBundleName, OnLoading); AsyncOperation ao = SceneManager.LoadSceneAsync(scenePath, loadSceneMode); while (!ao.isDone) { OnLoading?.Invoke(ao.progress); yield return null; } } #else yield return LoadAssetBundleAsync(assetBundleName, OnLoading); AsyncOperation ao = SceneManager.LoadSceneAsync(scenePath, loadSceneMode); while (!ao.isDone) { OnLoading?.Invoke(ao.progress); yield return null; } #endif } OnLoading?.Invoke(1); OnLoadOver?.Invoke(SceneManager.GetSceneByPath(scenePath)); CurrentScene = SceneManager.GetActiveScene(); //SceneManager.SetActiveScene(CurrentScene); } /// /// 异步清理内存 回收垃圾 /// /// public Coroutine ClearMemoryAsync() { return StartCoroutine(ClearMemory()); } /// /// 清理内存,释放空闲内存(异步) /// /// 协程迭代器 private IEnumerator ClearMemory() { yield return Resources.UnloadUnusedAssets(); GC.Collect(); GC.WaitForPendingFinalizers(); } /// /// 异步卸载资源 /// /// public Coroutine UnLoadAsstAsync(ResLoadMode resLoadMode, string assetBundleName, bool unloadAllLoadedObjects = false) { return StartCoroutine(UnLoadAsst(resLoadMode, assetBundleName, unloadAllLoadedObjects)); } private IEnumerator UnLoadAsst(ResLoadMode resLoadMode, string assetBundleName, bool unloadAllLoadedObjects = false) { yield return UnLoadAsset(ResLoadMode.Resourece, assetBundleName, unloadAllLoadedObjects); } /// /// 异步卸载场景 /// /// /// public Coroutine UnloadSceneAsync(Scene scene, TAction OnUnloading = null, TAction OnUnloadOver = null) { return StartCoroutine(UnloadScene(scene, OnUnloading, OnUnloadOver)); } private IEnumerator UnloadScene(Scene scene, TAction OnUnloading, TAction OnUnloadOver) { AsyncOperation ao = SceneManager.UnloadSceneAsync(scene); while (!ao.isDone) { OnUnloading?.Invoke(ao.progress); yield return null; } OnUnloadOver?.Invoke(); CurrentScene = SceneManager.GetActiveScene(); } public IEnumerator UnLoadAsset(ResLoadMode resLoadMode, string assetBundleName, bool unloadAllLoadedObjects = false) { if (resLoadMode == ResLoadMode.Resourece) { yield return Resources.UnloadUnusedAssets(); } else { if (AssetBundles.ContainsKey(assetBundleName)) { AssetBundles[assetBundleName].Unload(unloadAllLoadedObjects); AssetBundles.Remove(assetBundleName); } yield return null; } } /// /// 异步加载AB包清单 /// /// 协程迭代器 private IEnumerator LoadAssetBundleManifestAsync() { if (string.IsNullOrEmpty(AssetConfig.AssetBundleManifestName)) { throw new UnityException("请设置资源配置文件的 AssetBundleManifestName 属性,为所有AB包提供依赖清单!"); } else { if (AssetBundleManifest == null) { yield return LoadAssetBundleAsync(AssetConfig.AssetBundleManifestName, null); if (AssetBundles.ContainsKey(AssetConfig.AssetBundleManifestName)) { AssetBundleManifest = AssetBundles[AssetConfig.AssetBundleManifestName].LoadAsset("AssetBundleManifest"); UnLoadAsset(ResLoadMode.AssetBundle, AssetConfig.AssetBundleManifestName); } } } yield return null; } /// /// 异步加载AB包(提供进度回调) /// /// AB包名称 /// 加载中事件 /// 是否是加载清单 /// 协程迭代器 private IEnumerator LoadAssetBundleAsync(string assetBundleName, TAction onLoading) { assetBundleName = assetBundleName.ToLower(); if (!AssetBundles.ContainsKey(assetBundleName)) { AssetBundleCreateRequest abRequst = AssetBundle.LoadFromFileAsync(AssetConfig.AssetBundleRootPath + assetBundleName); yield return abRequst; while (!abRequst.isDone) { onLoading?.Invoke(abRequst.progress / 2); yield return null; } if (abRequst.assetBundle) AssetBundles.Add(assetBundleName, abRequst.assetBundle); else throw new UnityException($" 未加载到AB包【{assetBundleName}】!"); } onLoading?.Invoke(1); } /// /// 异步加载依赖AB包 /// /// AB包名称 /// 协程迭代器 private IEnumerator LoadDependenciesAssetBundleAsync(string assetBundleName) { #if UNITY_EDITOR if (AssetConfig.RuntimeMode != UpdateMode.Editor) { yield return LoadAssetBundleManifestAsync(); if (AssetBundleManifest != null) { string[] dependencies = AssetBundleManifest.GetAllDependencies(assetBundleName); foreach (string item in dependencies) { if (AssetBundles.ContainsKey(item)) continue; yield return LoadAssetBundleAsync(item, null); } } } #else yield return LoadAssetBundleManifestAsync(); if (AssetBundleManifest != null) { string[] dependencies = AssetBundleManifest.GetAllDependencies(assetBundleName); foreach (string item in dependencies) { if (AssetBundles.ContainsKey(item)) { continue; } yield return LoadAssetBundleAsync(item,null); } } #endif yield return null; } } }