需求:
1.能切换不同加载模式
开发阶段编辑器运行直接加载资源无需打ab包
测试或正式发布阶段通过ab包加载资源
2.缓存机制 能定时清理长时间未使用的资源内存
3.既有同步加载 也有异步加载
思路:
加载模式可以使用一个全局枚举变量控制
资源管理器中 包含不同的加载器 每个加载器都有同步和异步加载方法 要加载资源时调用资源管理器,管理器查询资源是否在缓存中,不在根据当前加载模式选择对应的加载器加载资源,
画张导图
实现:
首先定义加载模式枚举
LoadMode.cs
public enum LoadMode{
Editor, //编辑器模式(该模式直接加载资源)
AssetBundle, //ab包模式(该模式所有资源使用ab方式加载)
}
定义资源管理器类,它是一个单例
AssetManager.cs
public class AssetManager : MonoSingleton<AssetManager>{
[Header("当前资源加载模式:")]
public AssetLoadMode LoadMode = AssetLoadMode.Editor;
[Header("定时清理缓存间隔(秒):")]
public float ClearCacheDuration;
[Header("缓存数据驻留时间(秒)")]
public float CacheDataStayTime;
private IAssetLoader editorLoader;
private IAssetLoader abLoader;
private float cacheTimeTemp;
//缓冲区[key 为绝对路径]
private Dictionary<string, CacheDataInfo> cacheDataDic = new Dictionary<string, CacheDataInfo>();
public void InitMode(AssetLoadMode mode, float duration = 10f, float cacheStayTime = 9f) {
Debug.LogFormat("[AssetManager]初始化 当前加载模式:{0} 定时清理缓冲间隔:{1}s", mode, duration);
LoadMode = mode;
ClearCacheDuration = duration;
CacheDataStayTime = cacheStayTime;
editorLoader = new EditorAssetLoader();
abLoader = new AssetBundleLoader(GameConfigs.StreamingAssetABRootPath, GameConfigs.StreamingAssetManifestPath);
}
//同步加载
public T LoadAsset<T>(string path) where T : Object {
CacheDataInfo info = queryCache(path);
if (info != null) {
info.UpdateTick();
return info.CacheObj as T;
} else {
switch (LoadMode) {
case AssetLoadMode.Editor:
return editorLoader.LoadAsset<T>(path);
case AssetLoadMode.AssetBundler:
return abLoader.LoadAsset<T>(path);
}
return null;
}
}
//异步加载
public void LoadAssetAsync<T>(string path, UnityAction<T> onLoadComplate) where T : Object {
CacheDataInfo info = queryCache(path);
if (info != null) {
info.UpdateTick();
if (onLoadComplate != null) {
onLoadComplate(info.CacheObj as T);
}
} else {
switch (LoadMode) {
case AssetLoadMode.Editor:
StartCoroutine(editorLoader.LoadAssetAsync<T>(path, onLoadComplate));
break;
case AssetLoadMode.AssetBundler:
StartCoroutine(abLoader.LoadAssetAsync<T>(path, onLoadComplate));
break;
}
}
}
//检测缓冲区
private CacheDataInfo queryCache(string path) {
if (cacheDataDic.ContainsKey(path)) {
return cacheDataDic[path];
}
return null;
}
//加入缓冲区
public void pushCache(string path, Object obj) {
Debug.Log("[AssetManager]加入缓存:" + path);
lock (cacheDataDic) {
if (cacheDataDic.ContainsKey(path)) {
cacheDataDic[path].UpdateTick();
} else {
CacheDataInfo info = new CacheDataInfo(path, obj);
cacheDataDic.Add(path, info);
info.UpdateTick();
}
}
}
//清空缓冲区
public void RemoveCache() {
cacheDataDic.Clear();
}
//清理缓冲区
private void updateCache() {
Debug.Log("[AssetManager]清理缓存");
foreach (var iter in cacheDataDic.ToList()) {
if