任务系统简析
基本介绍
本项目中的任务系统总共分为两个部分:
- 基础部分:包含QuestManager.cs和QuestBase.cs两个脚本。
- 特例部分:指的是任务系统中自带的典型任务模板。例如:Trigger Quest模板、Fire Quest模板和Time Quest模板。
- Trigger Quest:用于判断一个物体是否到达指定区域的任务。通常可以用于判断玩家是否成功解救了被困人员,把他们接送到指定位置。
- Fire Quest:用于判断一个区域的火焰是否熄灭的任务。可以用于判断玩家是否成功扑灭指定区域的所有火焰。
- Time Quest:用于倒计时的任务。可以用于判断规定时间内某个任务是否完成。
- Other Quest:此任务为空白,用于后续拓展。
(在结尾有需要注意的地方提示。)
基础部分
QuestBase.cs
此脚本是所有任务的基类,包含一个任务该有的基本属性和一些虚函数。
Quest ID
1 | private string _QuestID; |
QuestID是用来标识每一个quest的整数,在任务需要被寻找或者操作的时候,需要用到ID。
(虽然说,现在并没有用到,但后续拓展可能会用。)
基本属性
1 | public QuestManager.QuestState.State state; |
任务的基本属性为任务状态:根据状态来对任务进行操作。
虚函数
1 | public virtual void OnQuestStart() |
在每一个具体的Quest中,需要去重写这些方法。
QuestManager.cs
此脚本用于管理所有的Quest,当运行场景时,会创造一个Game Object Quest Manager单例来进行管理。其中包含了所有的Quest State(任务状态),Quest Type(任务种类)以及一些任务初始化的方法。
创建单例
1 | // singleton |
任务状态
1 | // Quest状态类 |
这里详细说明一下一个任务从创建到结束的生命周期,可以用下面这张图来表示:
- 当你创建一个任务时,任务的基本状态会是Unprepared,这意味着你除了更改它的基本属性之外,无法对它进行任何操作,它也不会对正在进行中的项目有任何影响。
- 当任务状态为Unprepared时,它只会做一件事:检测任务的开始条件是否满足。任务的开始条件时它的前置任务队列清空。此时任务就会开始准备运行。它的状态也变为Prepared。
- 一般来说,在本项目中,一个任务一旦准备好,就立刻开始运行,基本不会有任务需要在运行途中手动设置该任务是否开始运行。所以它的状态会立刻变为Running。如果有例外的任务出现,那么增加一个bool变量控制即可。
- 任务开始运行以后,玩家就要进行一系列操作使得任务完成或者失败。(暂时默认成功,因为失败的话要和评分系统进行对接,还没整)任务完成后,状态变为Finished。
- 此时任务结束了,那么需要做的就是根据这个任务的后置任务列表,去找对应的任务前置列表中的这个任务,并把它删除。完成后任务状态变为End。
- 当任务状态为End时,任务就真正结束了。你无法对它进行任何操作。
任务种类
1 | // QuestType 类 |
这里写出了任务的特殊种类。(虽然现在写文档好像发现并没有用到这个,但是写出来还是会方便阅读一点。)
创建一个任务
1 | public QuestBase CreateQuest(int type_number) |
使用对应的Quest number来创建具体任务。0对应Trigger quest,1对应Time quest, 2对应Particle quest(也就是Fire quest, 取名是因为粒子系统)。
如果要输入其他数字的话,都会报错并提醒你去新建一个quest种类。
初始化任务
1 | public void InitQuest(QuestBase quest) |
这里初始化了一个任务的状态。把任务刚开始的状态设置为Unprepared。
特例部分
特例部分主要分为任务系统内部自带的几个任务类型:暂时有Trigger Quest、Fire Quest和Time Quest。
下面对于每个任务类型,都将进行代码的简要说明,并且运用示例来说明如何创建一个对应的任务。
Trigger Quest
Trigger Quest文件夹内有两个代码文件:
- Particle Quest:重写三个Quest Base虚函数。
- Particle Test:示例脚本。
Trigger Quest
1 | public class TriggerQuest : QuestBase |
Trigger Quest是一个继承于Quest Base的类,其中主要作用是重写了三个虚函数,然后在里面改变任务的状态。
Trigger Quest示例
假设我们有这样一个场景:
我们的任务需求是:让红色的方块落在右边的白色区域内。如果落在右边的区域内,那么就算任务成功,如果落在左边(其他)区域内,就算任务失败(此时任务也不会终止,而是继续检测)。
那我们就可以写一个脚本来创建任务,并挂在对应的任务物体上。(脚本内容直接用注释标明了)
1 | public class TriggerTest : MonoBehaviour |
在写完这个脚本后,我们需要:
- 把这个脚本挂在红色方块上。
- 把对应的区域拖到脚本里的空白处。
- 保存运行即可。
Fire Quest
Fire Quest文件夹内有三个代码文件:
- Fire Manager:管理一个区域里的火焰列表。
- Particle Quest:重写三个Quest Base虚函数。
- Particle Test:示例脚本。
Particle Quest
1 | public class ParticleQuest : QuestBase |
Particle Quest是一个继承于Quest Base的类,其中主要作用是重写了三个虚函数,然后在里面改变任务的状态。
Fire Quest示例
假设我们有这样一个场景:
我们的任务需求是:在这一个区域内有三个物体,他们都会着火。我们的目标是把这三处火全部扑灭,任务才算成功,否则任务失败。
那么首先,我们需要在创建一个空的GameObject,命名为FireManager,他会来管理这一块区域的火焰。我们把Fire Manager脚本挂到他身上,在列表里配置区域火焰。如下:
然后我们需要把这三个物体转换为着火物体并进行配置。(具体看另一篇如何转换火焰物体的文档。)
接下来我们把Particle Test脚本分别挂在每一个物体上,也就意味着我们创建了三个子任务。而这三个子任务构成了一个大的灭火任务。
下面是代码和注释(相同的部分就不注释了):
1 | public class ParticleTest : MonoBehaviour |
在写完这个脚本后,我们需要:
- 先创建一个Fire Manager(如果一个区域内有多个物体会着火)
- 把对应的区域内物体拖到Fire Manager里的空白处。
- 把这个脚本挂在对应着火物体上。
- 保存运行即可。
(注意:既然是灭火,那你肯定还需要一个水的particle system才能完成交互灭火的操作,如何创建一个“水流”,请参考火焰插件使用说明的文档。)
Time Quest
Time Quest文件夹内有两个代码文件:
- Time Quest:重写三个Quest Base虚函数。
- Time Quest Test:示例脚本。
Time Quest
和之前的Quest不同,Time Quest.cs里会直接开始一个time manager,由它来启动计时。(具体用法看计时器的使用文档)
1 | public class TimeQuest : QuestBase |
Time Quest示例
假设我们需要一个任务要在3s内完成,那么我们就可以写如下脚本来创建这个任务。
Time Quest Test
1 | public class TimeQuestTest : MonoBehaviour |
在写完这个脚本后,我们需要:
- 把这个脚本挂在一个GameObject上。
- 设定自定义的时间。
- 保存运行即可。
需要注意的地方
在创建一个任务时,你要想到以下几件事:
- 我要创建一个什么任务?它的类型是什么?
- 它会不会和别的任务有关联?它是否必须要在哪些任务之后进行?哪些任务又必须在它之后才能开始?
- 任务开始时会发生什么?
- 如何判断这个任务结束?
- 任务结束以后会发生什么?
根据这些去写对应的代码脚本,挂在对应的物体上即可。
一个完整的任务流程一个就包括之前的几个问题,之前的示例脚本并没有每一个都包含,只是简单的示例而已,在实际任务创建时,需要具体任务具体分析,借鉴示例中的方式进行操作。