对象池的作用:
避免对象反复实例化,造成性能的下降。
代码设计:
设计思路:
对象池,这个对象既可以是gameobject,也可以是class,甚至是其他的东西,所以需要利用到c#的泛型这个语法,并且需要一个基类PoolBase<T>,这个基类为抽象类,需要父类继承基类并且重写基类的方法。基类中需要包括三个关键的方法,分别是创建对象、把对象从池子中获取出来、把对象回收到池子里。这样能够有效的避免对象实例化,更有效的提高游戏运行时的性能。
除了对象池本身,还需要一个简单的管理器PoolManager去管理多个对象池,包括对象池的创建,获取指定对象池等方法。
设计模式:
PoolManager,单例模式,唯一实例,唯一控制。
数据结构:
PoolBase,可以使用栈或队列等结构存储对象,只要是获取任意对象的时间复杂度为O(1)的结构都可以。本人使用的是栈结构。
PoolManager,使用字典存储对象池, 能够快速匹配查找即可。
导图:
关键代码:
PoolBase.cs
public abstract class PoolBase<T>
{
}
对于不同的对象池来说,实例化对象的方式千差万别,所以把创建对象的方法设置为抽象函数。
public abstract T Create();
从池子中获取对象,直接获取栈顶对象,没有的话自动创建一个新的对象。
public virtual T Spawn()
{
if (_pool.Count > 0)
{
return _pool.Pop();
}
else
{
return Create();
}
}
把对象回收至池子,把对象入栈即可。不过需要考虑池子满了的情况,无法回收至池子的对象需要交由派生类自己处理。
public virtual bool Recycle(T obj)
{
if (obj == null)
{
return false;
}
if (_pool.Count >= _maxPoolCount)
{
return false;
}
_pool.Push(obj);
return true;
}
清空对象池
public virtual void ClearPool()
{
_pool.Clear();
}
PoolManager.cs
public class PoolManager
{
}
对对象池实例化,并且缓存至字典中,这里简单以GameObjectPool和ClassPool为例子。
private Dictionary<string, object> _poolDict = new Dictionary<string, object>();
public object CreateGameObjectPool(string name, string path, int maxPoolCount)
{
object pool = null;
if (_poolDict.TryGetValue(name, out pool) == false || pool == null)
{
GameObjectPool newPool = new GameObjectPool(path, maxPoolCount);
_poolDict.Add(name, newPool);
return newPool;
}
return pool;
}
public object CreateClassPool<T>(string name, int maxPoolCount) where T : class, new()
{
object pool = null;
if (_poolDict.TryGetValue(name, out pool) == false || pool == null)
{
ClassPool<T> newPool = new ClassPool<T>(maxPoolCount);
_poolDict.Add(name, newPool);
}
return pool;
}
public object GetPool(string name)
{
object pool = null;
_poolDict.TryGetValue(name, out pool);
return pool;
}
GameObjectPool.cs
为PoolBase的派生类,只需要关注GameObject的特性即可。
public class GameObjectPool : PoolBase<GameObject>
{
}
创建gameobject对象。
public override GameObject Create()
{
GameObject obj = GameObject.Instantiate(Resources.Load(_path)) as GameObject;
//GameObject prefab = AssetsLoad.LoadAssets<GameObject>(_path);
GameObject obj = GameObject.Instantiate(prefab);
obj.SetActive(true);
return obj;
}
从池子中获取gameobject对象,需要setactive。
public override GameObject Spawn()
{
GameObject obj = base.Spawn();
obj.SetActive(true);
return obj;
}
把gameobject对象回收至池子,回收失败需要销毁gameobject对象
public override bool Recycle(GameObject obj)
{
if (obj == null)
{
return false;
}
bool isSuccess = base.Recycle(obj);
if (isSuccess == false)
{
GameObject.Destroy(obj);
}
else
{
obj.transform.SetParent(_poolRoot);
}
return isSuccess;
}
ClassPool.cs
跟GameObjectPool同理,只需要关注自身特性即可。
public class ClassPool<T> : PoolBase<T> where T : class, new()
{
}
拓展:
可以根据实际的需求,添加其他方法,如批量从池子中获取对象或者批量回收对象。