用来理解对象池的简单示例使用了 https://blog.csdn.net/A13155283231/article/details/92098649 中的例子

ObjcetPool用来新建和回收游戏里的对象

public class ObjectPool
{
    private Queue<GameObject> m_PoolQueue;


    private string m_PoolName;

    protected Transform m_Parent;

    // 需要缓存的对象
    private GameObject prefab;

    // 最大容量
    private int m_MaxCount;

    protected const int m_DefaultMaxCount = 10;

    public GameObject Prefab { get => prefab; set => prefab = value; }

    public ObjectPool()
    {
        m_MaxCount = m_DefaultMaxCount;
        m_PoolQueue = new Queue<GameObject>();
    }

    public virtual void Init(string poolName, Transform transform)
    {
        m_PoolName = poolName;
        m_Parent = transform;
    }

    public virtual GameObject Get(Vector3 pos, float lifetime)
    {
        if (lifetime < 0)
        {
            return null;
        }
        GameObject returnObj;
        if (m_PoolQueue.Count > 0)
        {
            returnObj = m_PoolQueue.Dequeue();
        }
        else
        {
            // 池中没有可分配对象了,新生成一个
            returnObj = GameObject.Instantiate<GameObject>(prefab);
            returnObj.transform.SetParent(m_Parent);
            returnObj.SetActive(false);
        }
        // 使用PrefabInfo脚本保存returnObj的一些信息
        ObjectInfo info = returnObj.GetComponent<ObjectInfo>();
        if (info == null)
        {
            info = returnObj.AddComponent<ObjectInfo>();
        }

        info.PoolName = m_PoolName;
        if (lifetime > 0)
        {
            info.Lifetime = lifetime;
        }

        returnObj.transform.position = pos;
        returnObj.SetActive(true);

        return returnObj;
    }

    // "销毁对象" 其实是回收对象
    public virtual void Recycle(GameObject obj)
    {
        if (m_PoolQueue.Contains(obj))
        {
            return;
        }

        if (m_PoolQueue.Count > m_MaxCount)
        {
            // 对象池已满 直接销毁
            GameObject.Destroy(obj);
        }
        else
        {
            // 放入对象池
            m_PoolQueue.Enqueue(obj);
            obj.SetActive(false);
        }
    }

    public virtual void Destroy()
    {
        m_PoolQueue.Clear();
    }


}

上面代码主要理解下从池中取出对象后,要从池中移除该对象

因为对象使用结束后会回到池中

CubePool.cs

public class CubePool : ObjectPool
{
    public override GameObject Get(Vector3 pos, float lifetime)
    {
        GameObject obj;
        obj  =  base.Get(pos, lifetime);

        obj.GetComponent<Renderer>().material.color = Random.ColorHSV();

        return obj;
    }
}

ObjcetInfo.cs 用来记录对象信息 并且 定时回收对象

public class ObjectInfo : MonoBehaviour
{
    public float Lifetime = 0;
    public string PoolName;

    private WaitForSeconds m_WaitTime;

    private void Awake()
    {
        if (Lifetime > 0)
        {
            m_WaitTime = new WaitForSeconds(Lifetime);
        }
    }

    private void OnEnable()
    {
        if (Lifetime > 0)
        {
            StartCoroutine(CountDown(Lifetime));
        }
    }

    IEnumerator CountDown(float lifetime)
    {
        yield return m_WaitTime;
        ObjectPoolManager.Instance.RemoveGameObject(PoolName, gameObject);
    }
}

ObjcetPoolManager 用来管理多个对象池

public class ObjectPoolManager : Singleton<ObjectPoolManager>
{
    private Dictionary<string, ObjectPool> m_PoolDic;

    private Transform m_RootPoolTrans;

    public ObjectPoolManager()
    {
        m_PoolDic = new Dictionary<string, ObjectPool>();

        // 根对象池
        GameObject go = new GameObject("ObjcetPoolManager");
        m_RootPoolTrans = go.transform;
    }

    // 创建一个新的对象池
    public T CreateObjectPool<T>(string poolName) where T : ObjectPool, new()
    {
        if (m_PoolDic.ContainsKey(poolName))
        {
            return m_PoolDic[poolName] as T;
        }

        GameObject obj = new GameObject(poolName);
        obj.transform.SetParent(m_RootPoolTrans);
        T pool = new T();
        pool.Init(poolName, obj.transform);
        m_PoolDic.Add(poolName, pool);
        return pool;
    }

    public GameObject GetGameObject(string poolName, Vector3 position, float lifetTime)
    {
        if (m_PoolDic.ContainsKey(poolName))
        {
            return m_PoolDic[poolName].Get(position, lifetTime);
        }
        return null;
    }

    public void RemoveGameObject(string poolName, GameObject go)
    {
        if (m_PoolDic.ContainsKey(poolName))
        {
            m_PoolDic[poolName].Remove(go);
        }
    }
    
    // 销毁所有对象池
    public void Destroy()
    {
        m_PoolDic.Clear();javascript:void(0)
        GameObject.Destroy(m_RootPoolTrans);

    }
}

当然回收到对象池后可以进行属性重设的,不同种类的对象池可以重写这个方法重设不同的属性。比如

public virtual void Recycle(GameObject obj){
    //待分配对象已经在对象池中
    if(queue.Contains(obj)){
        Debug.LogWarning("the obj " + obj.name + " be recycle twice!" );
        return;
    }
    if( _freeObjCount > preAllocCount + autoIncreaseCount ){
        Destroy(obj);//当前池中object数量已满,直接销毁
    }else{
        queue.Enqueue(obj);//入队,并进行reset
        obj.transform.parent = this.transform;
        obj.SetActive(false);
        _freeObjCount++;
    }
}

扩展学习Unity对象池的管理

ObjectPoolContainer 对象容器 

ObjectPool 单一对象池 

PoolManager 对象池管理

扩展参考项目:https://github.com/KingSun5/UnityPool