[Unity3D]通用物件池類ResourcePool
阿新 • • 發佈:2019-01-06
通用物件池,使用時會將常用的物件至於池頂,如果設定了池的大小,超出池的未經常使用的物件將被移除,並且執行回撥,可在回撥中對移除物件進行其他操作。
可對壓入的物件進行命名,通過名字來進行查詢和刪除。
原始碼
using System.Collections;
using System.Collections.Generic;
using System;
using System.Linq;
namespace XM.Tool
{
public class ResourcePool<T> : IEnumerable<ResourcePool<T>.ResInfo> where T : class
{
public class ResInfo
{
public string path;
public T res;
public ResInfo(string p, T r)
{
path = p;
res = r;
}
public bool HasRes()
{
return res != null;
}
}
private Action<List<ResInfo>> _onRemove;
private int _poolMaxSize = 0;
private List<ResInfo> _poolLst = new List<ResInfo>();
//public List<ResInfo> Pool { get { return _poolLst; } }
public int PoolMaxSize { get { return _poolMaxSize; } }
public int PoolSize { get { return _poolLst.Count; } }
public ResourcePool(Action<List<ResInfo>> onRemove = null, int maxSize = 0)
{
_onRemove = onRemove;
_poolMaxSize = maxSize;
}
~ResourcePool()
{
//
Clear();
}
public void SetRemoveCallback(Action<List<ResInfo>> onRemove)
{
_onRemove = onRemove;
}
/// <summary>
/// 設定大小
/// </summary>
/// <param name="maxSize">大於等於0,0 表示無限大</param>
public void SetMaxSize(int maxSize)
{
_poolMaxSize = maxSize;
CheckSize();
}
public List<T> GetAllRes()
{
return _poolLst.Select((t) => { return t.res; }).ToList();
}
public List<string> GetAllPath()
{
return _poolLst.Select((t) => { return t.path; }).ToList();
}
public void Push(T res, bool checkSize = true, string path = "", bool updateExsit = false)
{
ResInfo resInfo = new ResInfo(path, res);
if (updateExsit)
{
//刪除已有的
List<ResInfo> removeLst = _poolLst.FindAll((t) => { return string.Compare(path, t.path) == 0; });
_poolLst.RemoveAll((t) => { return string.Compare(path, t.path) == 0; });
OnRemove(removeLst);
}
_poolLst.Add(resInfo);
if (checkSize)
{
CheckSize();
}
}
public void Push(List<T> resLst, bool checkSize = true, string path = "", bool updateExsit = false)
{
foreach (var res in resLst)
{
Push(res, false, path, updateExsit);
}
if (checkSize)
{
CheckSize();
}
}
public ResInfo Pop()
{
ResInfo res = null;
if (_poolLst.Count > 0)
{
int index = _poolLst.Count - 1;
res = _poolLst[index];
_poolLst.RemoveAt(index);
}
return res;
}
public ResInfo Pop(string path)
{
ResInfo res = null;
if (_poolLst.Count > 0)
{
int index = _poolLst.FindIndex(t => (t.path == path));
if (index != -1)
{
res = _poolLst[index];
_poolLst.RemoveAt(index);
}
}
return res;
}
public T PopExt(string path = null)
{
var res = Pop(path);
if (res == null)
{
return null;
}
return res.res;
}
public T PopExt()
{
var res = Pop();
if (res == null)
{
return null;
}
return res.res;
}
public ResInfo LookLast()
{
ResInfo res = null;
if (_poolLst.Count > 0)
{
res = _poolLst[0];
}
return res;
}
public ResInfo LookFirst()
{
ResInfo res = null;
if (_poolLst.Count > 0)
{
res = _poolLst[_poolLst.Count - 1];
}
return res;
}
public T Get(string path)
{
int resIndex = _poolLst.FindIndex((t) => { return string.Compare(path, t.path) == 0; });
if (resIndex == -1)
{//未找到
return null;
}
//移動到棧頂
ResInfo res = _poolLst[resIndex];
_poolLst.RemoveAt(resIndex);
_poolLst.Add(res);
return res.res;
}
public void Remove(T res)
{
List<ResInfo> removeLst = _poolLst.FindAll((t) => { return t.res == res; });
_poolLst.RemoveAll((t) => { return t.res == res; });
OnRemove(removeLst);
}
public void Remove(string path)
{
List<ResInfo> removeLst = _poolLst.FindAll((t) => { return t.path == path; });
_poolLst.RemoveAll((t) => { return t.path == path; });
OnRemove(removeLst);
}
public void Clear()
{
List<ResInfo> removeLst = new List<ResInfo>(_poolLst);
_poolLst.Clear();
OnRemove(removeLst);
}
public void CheckSize()
{
if (_poolMaxSize == 0)
{
return;
}
int overflowSize = _poolLst.Count - _poolMaxSize;
if (overflowSize > 0)
{//超出儲存範圍
//移除棧底元素
List<ResInfo> removeLst = _poolLst.GetRange(0, overflowSize);
_poolLst.RemoveRange(0, overflowSize);
OnRemove(removeLst);
}
}
private void OnRemove(List<ResInfo> removeLst)
{
if (_onRemove != null)
{//移除元素回撥
_onRemove(removeLst);
}
}
public IEnumerator<ResInfo> GetEnumerator()
{
return ((IEnumerable<ResInfo>)_poolLst).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<ResInfo>)_poolLst).GetEnumerator();
}
}
}
使用方式
using System.Collections.Generic;
using UnityEngine;
using XM.Tool;
public class Test : MonoBehaviour
{
//物件池
ResourcePool<GameObject> _pool;
void Start()
{
//初始化
_pool = new ResourcePool<GameObject>(OnRemove, 5);
}
private void OnRemove(List<ResourcePool<GameObject>.ResInfo> objs)
{
//銷燬移除的物件
foreach (var obj in objs)
{
//是否存在
if (obj.HasRes())
{
//銷燬
Destroy(obj.res);
}
}
}
public GameObject GetObj()
{
GameObject obj = null;
//優先從pool中獲取
obj = _pool.PopExt();
if (null == obj)
{//否則建立
obj = new GameObject(Time.time.ToString());
}
else
{//啟用物體
obj.SetActive(true);
}
return obj;
}
public void RecycleObj(GameObject obj)
{
//禁用物體
obj.SetActive(false);
//置入pool中,等待複用
_pool.Push(obj);
}
//當前回收的物件名字
string _recycleObjName = "";
public void OnGUI()
{
//建立物件
if (GUILayout.Button("Create Obj"))
{
GetObj();
}
//回收物件
_recycleObjName = GUILayout.TextField(_recycleObjName);
if (GUILayout.Button("Recycle Obj"))
{
GameObject obj = GameObject.Find(_recycleObjName);
if (null != obj)
{
RecycleObj(obj);
}
}
//清理物件池
if (GUILayout.Button("Clear Pool"))
{
_pool.Clear();
}
}
}