unity 之简单的实例(clone)对象池

发布时间 2023-05-04 11:43:49作者: 赵不灰
using System;
using System.Collections.Generic;
using UnityEngine;


public class GameObjectPoolEntity 
{
    public  Queue<GameObject> QueueList;
    public string Name;
    public GameObject Pool0bj;
}

public class QGGameObjectPool : IDisposable
{
    private Dictionary<int, GameObjectPoolEntity> m_PoolDic;
    private Dictionary<int, List<int>> m_InstanceIdDic;

    public QGGameObjectPool()
    {
        m_PoolDic = new Dictionary<int, GameObjectPoolEntity>();
        m_InstanceIdDic = new Dictionary<int, List<int>>();
    }

    //取池
    public GameObject Spawn(GameObject prefabObj,  Action<GameObject> onComplete = null)
    {
        lock (m_PoolDic)
        {                        
            int instanceId = prefabObj.GetInstanceID();
            m_PoolDic.TryGetValue(instanceId, out var poolEntity);
            if (poolEntity == null)
            {
                poolEntity = new()
                {                    
                    Pool0bj = new GameObject(prefabObj.name + "Pool"),
                    Name = prefabObj.name,
                    QueueList = new Queue<GameObject>()
                };
                m_PoolDic[instanceId] = poolEntity;
            }
            else
            {
                if (poolEntity.QueueList.Count > 0)
                {
                    GameObject obj  = poolEntity.QueueList.Dequeue();
                    obj.SetActive(true);
                    onComplete?.Invoke(obj);
                    return obj;
                }
            }
            GameObject newObj = GameObject.Instantiate(prefabObj);
            newObj.transform.parent = poolEntity.Pool0bj.transform;
            m_InstanceIdDic.TryGetValue(instanceId, out var lst);           
            lst??= new List<int>();
            lst.Add(newObj.GetInstanceID());
            m_InstanceIdDic[instanceId] = lst;
            newObj.SetActive(true);
            onComplete?.Invoke(newObj);
            return newObj;
        }
    }

    //回池
    public void Despawn(GameObject gameObject)
    {
        lock (m_PoolDic) 
        {                         
            int instanceId = GetInstanceId(gameObject.GetInstanceID());      
            m_PoolDic.TryGetValue(instanceId, out var poolEntity);
            if (poolEntity != null)
            {
                gameObject.SetActive(false);
                poolEntity.QueueList.Enqueue(gameObject);                
            }
        }
    }

    private int GetInstanceId(int instanceID) 
    {
        foreach (var item in m_InstanceIdDic)
        {
            foreach (var obj in item.Value) 
            {
                if (obj == instanceID) 
                {
                    return item.Key;
                }
            }
        }
        return 0;
    }


    public void Dispose()
    {
        m_PoolDic.Clear();
        m_InstanceIdDic.Clear();
    }
}