1. 程式人生 > >[Unity3D]通用物件池類ResourcePool

[Unity3D]通用物件池類ResourcePool

通用物件池,使用時會將常用的物件至於池頂,如果設定了池的大小,超出池的未經常使用的物件將被移除,並且執行回撥,可在回撥中對移除物件進行其他操作。
可對壓入的物件進行命名,通過名字來進行查詢和刪除。

原始碼

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

這裡寫圖片描述