using System.Collections.Generic;
using UnityEngine;
public class SimplePool : MonoBehavior
{
// 物体的池子,用字典表示。键为种类 ID,值是同类物体的队列
// 以预制体的 ID 作为每个种类的标识 ID
private Dictionary<int, Queue<GameObject>> m_Pool = new Dictionary<int, Queue<GameObject>>{};
// 记录所有离开对象池的物体。键是物体引用,值是种类 ID
// 离开对象池的物体会从 m_Pool 中离开,但是要记录在 m_OutObjs 字典里
private Dictionary<GameObject, int> m_OutObjs = new Dictionary<GameObject, int>{};
// 创建物体,预制体由调用者自备
public GameObject Create(GameObject prefab)
{
// 以预制体的物体 ID,作为该类型物体的 ID
int id = prefab.GetInstanceID();
// 尝试从对象池中获取这个物体
GameObject go = _GetFromPool(id);
if(go == null)
{
// 取不到物体,就根据预制体创建物体
go = Instantiate<GameObject>(prefab);
// 如果初次遇到这类物体,需要添加一个新的类型
if(!m_Pool.ContainsKey(id))
{
m_Pool.Add(id, new Queue<GameObject>());
}
}
// 标记新创建的物体离开了对象池
m_OutObjs.Add(go, id);
return go;
}
// 销毁(回收)物体
public void Destroy(GameObject go)
{
// 判断物体是不是由对象池创建
if(!m_OutObjs.ContainsKey(go))
{
Debug.LogWarning("回收的物体并不是对象池创建的!" + go);
return;
}
// 该物体属于哪个种类
int id = m_OutObjs[go];
go.transform.parent = transform;
go.SetActive(false);
// 加入队列,并且去掉离开的标记
m_Pool[id].Enqueue(go);
m_OutObjs.Remove(go);
}
// 从对象池中根据类型 ID 取出物体。如果类型不存在或者物体暂时用完了,返回 null
private GameObject _GetFromPool(int id)
{
if(!m_Pool.ContainsKey(id) || m_Pool[id].Count == 0)
{
return null;
}
GameObject obj = m_Pool[id].Dequeue();
obj.SetActive(true);
return obj;
}
}
网友评论