1.对象池概述
对象池是存放对象的缓冲区。用户可以从缓冲区中放入/取出对象。一类对象池存放一类特定的对象。那么对象池有什么用呢?在游戏中,经常会有产生/销毁大量同类游戏对象的需求,比如游戏中源源不断的敌人、频繁刷新的宝箱、乃至一些游戏特效(风、雨等)。如果没有一种比较好的机制来管理这些对象的产生和销毁,而是Instantiate和Destroy,将使你的游戏性能大大下降,甚至出现卡死、崩溃……
2.对象池实现
简而言之,就是当需要使用一个对象的时候,直接从该类对象的对象池中取出(SetActive(true)),如果对象池中无可用对象,再进行Instantitate。而当不再需要该对象时,不直接进行Destroy,而是SetActive(false)并将其回收到对象池中。下面直接贴下代码:
2.1实现对象池ObjectPool
public class ObjectPool : MonoBehaviour
{
//池中对象
private PooledObject prefab;
//存储可用对象的缓冲池
private List<PooledObject> objectedPools = new List<PooledObject>();
//从池中取出对象,返回该对象
public PooledObject GetObject()
{
PooledObject obj;
int objectedPoolsIndex=objectedPools.Count-1;
if (objectedPoolsIndex >= 0)
{
obj = objectedPools[objectedPoolsIndex];
objectedPools.RemoveAt(objectedPoolsIndex);
obj.gameObject.SetActive(true);
}
else //池中无可用obj
{
obj = Instantiate<PooledObject>(prefab);
obj.transform.SetParent(transform, false);
obj.pool = this;
}
return obj;
}
//向池中放入对象
public void AddObject(PooledObject obj)
{
obj.gameObject.SetActive(false);
objectedPools.Add(obj);
}
//静态方法,创建并返回对象所属的对象池
public static ObjectPool GetPool(PooledObject prefab)
{
GameObject obj;
ObjectPool pool;
//编辑器模式下检查是否有同名的pool存在,放置重复创建pool
if (Application.isEditor)
{
obj = GameObject.Find(prefab.name + "Pool");
if (obj)
{
pool = obj.GetComponent<ObjectPool>();
if (pool != null)
{
return pool;
}
}
}
obj = new GameObject(prefab.name + " Pool");
DontDestroyOnLoad(obj);
pool = obj.AddComponent<ObjectPool>();
pool.prefab = prefab;
return pool;
}
}
2.2 运用对象池
/// <summary>
/// 所有需要使用对象池机制的对象的基类
/// </summary>
public class PooledObject : MonoBehaviour
{
//归属的池
public ObjectPool pool { get; set; }
//场景中某个具体的池
[System.NonSerialized]
private ObjectPool poolInstanceForPrefab;
//回收对象到对象池中
public void ReturnToPool()
{
if (pool)
{
pool.AddObject(this);
}
else
{
Destroy(gameObject);
}
}
/// <summary>
/// 返回对象池中可用对象的实例
/// </summary>
public T GetPooledInstance<T>() where T : PooledObject
{
if (!poolInstanceForPrefab)
{
poolInstanceForPrefab = ObjectPool.GetPool(this);
}
return (T)poolInstanceForPrefab.GetObject();
}
}