Unity 对象池
程序员文章站
2022-07-13 15:01:27
...
参考 https://blog.csdn.net/wangjiangrong/article/details/80196676
代码结构
ObjcetPool用来新建和回收游戏里的对象(prefab) 如 setActive(false)啥的
ObjcetPool.cs
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 Remove(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 用来对游戏里的对象进行特殊处理 (这里是改变颜色)
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;
}
}
ObjcetPoolManager 用来管理多个对象池
ObjcetPoolManager.cs
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();
GameObject.Destroy(m_RootPoolTrans);
}
}
MoveUp.cs 就一个向上运动的脚本
void Update()
{
transform.position += Vector3.up * Time.deltaTime * 2;
}
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);
}
}
测试主程序
public class PoolDemo : MonoBehaviour
{
private ObjectPool m_TestPool;
public GameObject Prefab;
public Button TestButton;
// Start is called before the first frame update
void Start()
{
m_TestPool = ObjectPoolManager.Instance.CreateObjectPool<CubePool>("CubePool");
m_TestPool.Prefab = Prefab;
TestButton.onClick.AddListener( () => {
ObjectPoolManager.Instance.GetGameObject("CubePool", new Vector3(0, 0, 0), 2);
});
}
// Update is called once per frame
void Update()
{
}
}
上一篇: 十大经典策略之一 - Dual Thrust策略(期货)
下一篇: es近实时搜索原理