对象池也是开发中很常用的东西,
使用对象池无非就是解决两个问题:
- 一是减少new时候寻址造成的消耗,该消耗的原因是内存碎片。
- 二是减少Object.Instantiate时内部进行序列化和反序列化而造成的CPU消耗
简易对象池
class Fish
{
}
var fishPool = new SimpleObjectPool<Fish>(() => new Fish(), 100);
Debug.LogFormat("fishPool.CurCount:{0}", fishPool.CurCount);
var fishOne = fishPool.Allocate();
Debug.LogFormat("fishPool.CurCount:{0}", fishPool.CurCount);
fishPool.Recycle(fishOne);
Debug.LogFormat("fishPool.CurCount:{0}", fishPool.CurCount);
for (int i = 0; i < 10; i++)
{
fishPool.Allocate();
}
Debug.LogFormat("fishPool.CurCount:{0}", fishPool.CurCount);
SimpleObjectPool 构造函数 第一个是 创建对象的方法,第二个是初始的数量
fishPool.Allocate() 是从池中取一个对象,那么问题来了,当取完了怎么办 ? 直接返回一个 null 吗? 不,我认为当池中取完后再通过创建对象的方法创建一个对象返回时比较好的解决办法。
fishPool.Recycle(fishOne) 当不再需要该对象的时候,就重新放在池中
安全扩展对象池
我们有可能将一个 IPoolable 对象回收两次。为了解决这个问题,我们可以在SafeObjectPool 维护一个已经分配过的对象容器来记录对象是否被回收过,也可以在 IPoolable 对象中增加是否被回收的标记。
class Bullet : IPoolable
{
public void OnRecycled()
{
Debug.Log("回收了");
}
public bool IsRecycled { get; set; }
public static Bullet Allocate()
{
return SafeObjectPool<Bullet>.Instance.Allocate();
}
public void RecycleToCache()
{
SafeObjectPool<Bullet>.Instance.Recycle(this);
}
}
SafeObjectPool<Bullet>.Instance.Init(20);
var bullet = Bullet.Allocate();
Debug.Log(SafeObjectPool<Bullet>.Instance.CurCount);
bullet.RecycleToCache();
Debug.Log(SafeObjectPool<Bullet>.Instance.CurCount);
在 UniWb 中你会发现, 很多地方都用到了,SafeObjectPool 去管理内存,嗯,真的省事了很多。