赞
踩
前面一文基于Addressable的资源加载更新记录了资源的加载,本文将紧贴资源的加载,结合设计模式中的享元模式的理念设计对象缓存池,避免在游戏过程中频繁的进行创建和销毁的工作。
在基于Addressable的资源加载更新一文中有提到缓存池的结构,主要分为以下几大模块:
private class CacheList { /// <summary> /// 资源地址 /// </summary> public string Address; /// <summary> /// 缓存列表 /// </summary> private Stack<T> caches = new Stack<T>(); /// <summary> /// 正在使用的列表 /// </summary> private HashSet<T> references = new HashSet<T>(); /// <summary> /// 清理参数 /// </summary> public float Exceed = AssetPoolManager.Exceed; /// <summary> /// 模板 /// </summary> public UnityEngine.Object Prefab; private int maxReferenceNumber = 0; public bool isAddressableAssets; /// <summary> /// 总计缓存数量 /// </summary> public int Count { get { return this.references.Count + this.caches.Count; } } /// <summary> /// 可以使用的缓存对象的数量 /// </summary> public int CachesCount { get { return this.caches.Count; } } /// <summary> /// 添加使用项 /// </summary> /// <param name="t"></param> public void AddReference(T t) { if (this.references.Add(t)) { this.maxReferenceNumber = this.references.Count > this.maxReferenceNumber ? this.references.Count : this.maxReferenceNumber; } } /// <summary> /// 从缓存池中取出一个项使用 /// </summary> /// <returns></returns> public T Pop() { if (this.caches.Count > 0) { T _reference = this.caches.Pop(); this.AddReference(_reference); return _reference; } else { throw new System.Exception(string.Format("{0} CacheList's caches is empty but use pop", Prefab.name)); } } /// <summary> /// 使用完成之后放回缓存池 /// </summary> /// <param name="t"></param> public void Push(T t) { this.caches.Push(t); this.references.Remove(t); InitInfomation(); } public void Delete(T t) { this.references.Remove(t); GameObject.Destroy(t.gameObject); } /// <summary> /// 使用计算 /// </summary> internal void InitInfomation() { this.maxReferenceNumber = this.references.Count; } public void ClearCaches(Dictionary<T, CacheList> lookup) { foreach (var obj in this.caches) { lookup.Remove(obj); GameObject.Destroy(obj.gameObject); } foreach (var obj in this.references) { lookup.Remove(obj); GameObject.Destroy(obj.gameObject); } this.caches.Clear(); this.references.Clear(); Prefab = null; if (isAddressableAssets) AddressableManager.Instance.UnLoadAsset(Address); } /// <summary> /// 清理多余的缓存资源 /// </summary> /// <returns></returns> public List<T> CleanCache() { int cleanCount = this.Count - ((int)(this.maxReferenceNumber * Exceed)); if (cleanCount > 0) { List<T> list = new List<T>(); for (int i = 0; i < cleanCount; i++) { list.Add(this.caches.Pop()); } return list; } return null; } }
为方便不同的资源类型复用缓存池的逻辑,这里将采用泛型来实现缓存的逻辑,将CacheList类设计为AddressablePool的嵌入类类型。AddressablePool负责判断加载逻辑是使用缓存池的对象还是重新创建新的对象。
public void AddTemplate(string address, UnityEngine.Object obj, bool isAddressabel=true, float Exceed = AddressableManager.Exceed) { if (!this.pools.ContainsKey(address)) { CacheList cache = new CacheList(); cache.Address = address; cache.Prefab = obj; cache.Exceed = Exceed; cache.isAddressableAssets = isAddressabel; isLoad = false; this.pools.Add(address, cache); } else { Helper.LogError("速查,出现同名资源:" + address); } }
在界面上直接传入模板(GameObject),也能使用这个缓存池的方法(在飘提示文字的时候经常用到),如果是需要加载,则在加载完成之后也调用该方法,只需要用个标记来区分是加载的模板还是外部直接传入的模板(资源清理时,加载的模板需要调用释放接口。界面上直接传入的则不用)。
public void LoadAsset(string address, System.Action<T> onComplete, float Exceed = AssetPoolManager.Exceed) { isLoad = true; CacheList cache; if (this.pools.TryGetValue(address, out cache)) { isLoad = false; var obj = LoadAssetByTemplate(address); if (obj != null) { onComplete(obj); } else { Helper.LogWarning("加载资源失败,请检查 :" + address); } } else { List<System.Action<T>> callBackList; if (loadCallBack.TryGetValue(address, out callBackList)) { callBackList.Add(onComplete); } else { callBackList = new List<System.Action<T>>(); callBackList.Add(onComplete); loadCallBack.Add(address, callBackList); AddressableManager.Instance.LoadAsset<GameObject>(address, (objAsset) => { AddTemplate(address, objAsset, true, Exceed); isLoad = false; var list = loadCallBack[address]; if (objAsset != null) { if(list!=null&&list.Count>0) { for (int i = 0; i < list.Count; i++) { var obj = LoadAssetByTemplate(address); list[i](obj); } } } else { Helper.LogWarning("加载资源失败,请检查 :" + address); } loadCallBack.Remove(address); }, () => { Helper.LogWarning("加载资源失败,请检查 :" + address); }); } } }
private void cleanCache() { if (isLoad) return; InitInfomation(); foreach (var info in this.pools) { List<T> temps = info.Value.CleanCache(); if (temps != null) { foreach (var obj in temps) { this.lookup.Remove(obj); GameObject.Destroy(obj.gameObject); } } } List<string> deleteList = new List<string>(); foreach (var info in this.pools) { if (info.Value.Count == 0) { info.Value.ClearCaches(this.lookup); deleteList.Add(info.Key); } } foreach (var info in deleteList) { pools.Remove(info); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。