在B站上学习阿严教程,记录一下对象池模式的学习
由图,一共是四个步骤:
1 在Pool 脚本中生成预备对象。具体包括 Initialize()初始化队列,Copy() 复制预备对象并初始化禁用状态, 放入队列。
2 玩家进行开火,从PoolManager脚本中Release()找到对应的Pool.prefab(因为游戏中不会只有一个对象池),通过对象池管理器脚本中的字典< prefab, Pool >,对应到当前使用的对象是在哪个池子里。从中取出。
3 得到对应的池子,在池子Pool脚本中PreparedObject()返回队里的一个可用对象将状态设置为启用。
4 Pool脚本中,可用对象AvailableObject()一从队列头取出,马上放回队尾,供下次使用。
1:Pool.cs
public void Initialize(Transform parent)
{
queue = new Queue<GameObject>();
this.parent = parent;
for (var i = 0; i < size; i++)
{
queue.Enqueue(Copy());
}
}
GameObject Copy()
{
var copy = GameObject.Instantiate(prefab, parent);
copy.SetActive(false);
return copy;
}
2:
Player.cs
PoolManager.Release(projectile1, muzzleMiddle.position);
PoolManager.cs
static Dictionary<GameObject, Pool> dictionary;
public static GameObject Release(GameObject prefab)
{
if(!dictionary.ContainsKey(prefab))
{
return null;
}
return dictionary[prefab].PreparedObject();
}
3:
Pool.cs
public GameObject PreparedObject()
{
GameObject preparedObject = AvailableObject();
preparedObject.SetActive(true);
return preparedObject;
}
4:Pool.cs
GameObject AvailableObject()
{
GameObject availableObject = null;
availableObject = queue.Dequeue();
queue.Enqueue(availableObject);
return availableObject;
}
如何判断对象池应该有多大?
在PoolManager脚本中,写一个CheckPoolSize(),在Ondestroy时调用。主要内容就是判断当前队列的大小与我们预设的大小是否符合,不符合打印出来,调整预设大小。
private void OnDestroy()
{
CheckPoolSize(playProjectilePools);
}
void CheckPoolSize(Pool[] pools)
{
foreach(var pool in pools)
{
if(pool.RuntimeSize > pool.Size)
{
Debug.Log(
string.Format("Pool : {0} 的实际尺寸{1}大于预留尺寸{2}",
pool.Prefab.name,
pool.RuntimeSize,
pool.Size));
}
}
}