对象池的概念:
对象池是一种创建型设计模式,一些需要频繁创建删除的物体比如子弹,利用InInstantiate()和Destroy()方法会非常消耗性能,而对象池利用Unity中对象中SetActive()方法设置物体是否可以进行交互,将需要频繁使用的物体通过设置它的可互动性与否,在需要时从池中取出,不需要时放回,从而减少性能的消耗。
总的来说就是如果你大量的物体经常销毁或创建,会导致消耗非常高的计算机性能,直观感受就是掉帧,而通过使用对象池的方法,让暂时不用,要销毁的对象先SetActive(false)让它不可视,无法参与物理运算,等需要时在让他恢复原本的状态,这样就可以减少创建和销毁的使用。
如何编写对象池:
先给出一个不错的视频教程,你可以试着看视频或者继续看我的说明,M_Studio的教程适合新手,但是这个视频的对象池比较基础,适用性窄,我这里讲解也是基础的对象池打牢基础,下一章节我会讲解如何提升这个对象池:
Unity教程:利用对象池设计制作Dash冲锋残影效果!(多P合集)_哔哩哔哩_bilibili
以下给出代码:
public class ObjectPools : MonoBehaviour
{
[Header("对象池所管理对象")]
public GameObject PoolOject;
[Header("池组单位数量")]
public int PoolCount;
public static ObjectPools instance;//单列模式静态对象
protected Queue<GameObject> Pools = new();//对象池容器
private void Awake()
{
if (instance == null)
instance = this;
else
{
Destroy(this);
return;
}
CreateReference();
}
public void CreateReference()
{
for (int i = 0; i < PoolCount; i++)
BackPools(Instantiate(PoolOject, transform));
}
public GameObject OutPools()
{
if(Pools.Count == 0)
CreateReference();
GameObject game = Pools.Dequeue();
room.gameObject.SetActive(true);
return game;
}
public void BackPools(GameObject game)
{
Pool.transform.SetParent(transform);
Pool.gameObject.SetActive(false);
Pools.Enqueue(Pool);
}
}
看不懂?没关系,我来一一说这些方法和参数的作用。
参数:
PoolOject肯定是我们对象池要管理的预制体类型,比如子弹。
Pools,对象池既然名字里有池,还保存很多不用的对象,那么肯定需要一个容器,通常情况我们肯定需要经常将容器中的对象元素取出并且放回,那么List容器和数组可能是大多数人喜欢用的,但是使用它们取出放回,数组肯定第一时间排除,然后取出容器元素就要把他从容器中删除,如果使用List删除元素如果位于靠首位的元素就会移动整个容器元素的位置,也是非常消耗性能的,而且List容器存取频繁使用的都是容器尾的元素,我们需要一个先进先出这样的容器,Queue容器就成为了我们的首选!Queue容器就提供两个理想的方法,Dequeue()从容器中取出首位的元素并将它从容器中移除,Enqueue(T t)则是将元素放回容器末尾,具有先进先出的特点,刚好符合我们的需要。
PoolCount代表对象池容器每次实例化新增元素的数量,这个参数可有可无,因为我们不一定需要一次性创建很多个元素,但是如果这个元素的使用量比较大,比如为冲锋枪子弹的创建,我们就可以使用这个参数一次创建多个避免频繁地类之间的方法调用。
Instance是对象池类本身,代表这是一个单例模式的设计方式,这个设计方式间接便于使用,但是可扩展性差。
执行过程
接下来就是方法,Awake()方法就是初始化这个对象池,将它作为一个单例,当之后我们要使用这个对象池时,我们只需要用这个类型名.instance就能获得这个对象然后使用内部的方法,管理对象了,这也是单例模式的特点之一,方便调用。当这个方法执行到CreateReference()【其实从对象池的特性来说,这个方法是没必要调用的】就会创建几个对象并作为预留通过BackPools放置在容器中,设置元素位于容器的游戏下并且不可见,被取出的元素放回也可以通过这一步设置,而取出元素则是OutPools()方法,当容器中没有元素时就会调用CreateReference()方法在新增新的元素放到容器中,然后打开它的交互,这就是一个基础的对象池。