Unity学习记录/ #5 工厂模式与对象池
一、前言
Hello大家好,这里是我的Unity学习简单笔记,前4期专栏都是讲到了一些Unity内置的功能,所以这期想来写写有关于游戏编程设计模式的东西。
程序员为什么需要设计模式呢?简单来说,我们的游戏需要 架构 和 性能。这就像整理你的房间一样,你总不能让你的游戏架构和你的房间一样乱糟糟的吧?合理有效地使用设计模式,就能够把我们的房间(也就是游戏)变得整洁干净,还能让你装下更多的东西。这也能很好地解耦你的代码,让他们变得更加模块化且方便调试。
那种代码库看上去是间豪华酒店,里面的门房随时准备满足你心血来潮的需求。

二、简单工厂模式
在你学习Unity游戏制作的过程中,你肯定会接触到这一个API "Instantiate();" 。它往往出现在我们需要去直接生成某个预制体(Prefab)的时候,可以让我们直接指定生成。
假如我们现在有一个蓝色史莱姆的预制体,当我们需要将它生成在广袤的草原上时,就可以使用到 Instantiate 并给定要生成的具体位置。

勇士在草原上进行冒险的时候,只会有一种蓝色史莱姆吗?当然还会有红色、绿色的史莱姆,甚至还会有会飞的、跑得更快的史莱姆等等。最简单的方式就是我们一个一个去制作相关的预制体,但那样太浪费时间了而且根本不像我们程序员的风格,这时我们就可以搬出工厂模式了。
工厂模式(Factory Pattern),它就像一座工厂一样基于原型并根据不同需求,能够制造出不同的产品进行出售,这样一来我们就能通过代码来产出不同的内容了。


简单分享一种泛型的抽象工厂模式(工厂模式,每个人可能都会有不同的写法,基于原理其实都是一样的效果)。

思路就是先写一个 IFactory 的泛型 T 接口(interface),它包含一个泛型 T 的Create方法。接着让抽象类 abstract Factory 继承接口,同样包含泛型 T Create方法 不进行具体的实现。当我们需要特定的工厂时,再编写一个对应的工厂类(也可以写成单例,SO的写法也是一种解耦),在那个特定的工厂类中实现 Create 方法,赋予预制体,外部引用工厂SO从而制作出不同的物体。

三、对象池
在了解完 Instantiate 和 工厂模式 后,我们对Unity生成物体就有一个基本的方法了。兴趣高涨的我们迫不及待地打开Unity在一个简单场景中利用学过的知识疯狂点击生成物体,随着物品产生的越来越多,电脑君不堪重负地倒下了。没错,Instantiate 生成物品到场景中的方法其实是非常消耗电脑内存的一个方法,我们每次利用它生成一个物体的时候,这个物体就会占用到一格电脑内存,而当我们不再需要这个物体将它 Destroy 销毁掉,原本占用的内存则会产生垃圾回收,也就是GC。这是我们非常不愿意看到的一见事情,它将损耗电脑大量的内存,导致我们的游戏掉帧甚至死机。为解决这种问题,伟大的前人为我们创造了 对象池模式(Object Pool)。

首先,你需要了解我们何时需要对象池。游戏开发师 Bob Nystrom 说:
这个模式广泛应用于可见的事物上,比如游戏实体和视觉效果, 但是它也可在不那么视觉化的数据结构上使用,比如正在播放的声音。 在以下情况中使用对象池:
需要频繁创建和销毁对象。
对象大小相仿。
在堆上进行对象内存分配十分缓慢或者会导致内存碎片。
每个对象都封装了像数据库或者网络连接这样很昂贵又可以重用的资源
对象池模式,简单来说就是我们在一开始就生成好我们所有所需要的物体,让他们一开始就站好各自在内存中的位置,在我们需要的时候就将物体启用 gameObject.SetActive(true); 而在当我们不再需要它时,选择 gameObject.SetActive(false); 这样一来在游戏的后续这些物体就不会因为产生和销毁而大量损耗性能产生GC。我们可以选择创建简单的对象池来使用,在Unity 2021.1版本以后,Unity官方也在API中为我们提供了可选择对象池的写法。

基本对象池写法,要确定数据结构类型(List、Queue、Stack等)、对象、预先实例化次数,在运行的一开始预先实例化好所有的物体并将他们按数据结构存进对象池,可以将对象池写成单例或SO。

其次还需要一个返回对应对象的 GetFromPool 方法,让外界能够获取到还没处于启用状态的对象。这里就可以结合之前的工厂模式,工厂从对象池里获取到对象后进行二次加工并启用的一个流程。

在2021.1版本以后,我们就可以选择使用Unity官方提供的对象池API,其中还提供了很多的方法来优化和方便使用对象池,是个非常不错的选择,具体的使用方法我们就不深究下去了,本篇目的也只是简单介绍一下这两种设计模式。

设计模式其实也是一个大坑,从前的编程员不断试错积累经验方法,为我们留下了许许多多的设计模式,只要我们合理运用它就能为我们的游戏架构创造出不一样的精彩。
本篇推荐教程:
1.游戏编程模式 (tkchu.me)
2.阿严的对象池:
https://www.bilibili.com/video/BV14T4y197bW?share_source=copy_web
3.咖喱饭游戏的工厂模式和对象池:
https://www.bilibili.com/video/BV1Ty4y1p7WS?share_source=copy_web
https://www.bilibili.com/video/BV1af4y1674L?share_source=copy_web
(以上,祝好胃口)