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;
}
}
}