achevery

15、追逐玩家

现在我们的AI无法做出任何决策,它总是执行相同的决策。我们先把感知系统中的相关信息提供给AI,让AI知道如何做出决策,然后我们会修改行为树。我们首先需要创建新的黑板键,这样我们就能在行为树上保存这些信息。打开”BB_EnenmyAI “,在左侧的“黑板”选项卡中,点击“新建”按钮,选择“对象”类型,将这个新建命名为“Target Actor”。在右侧的“黑板详细信息”面板中,在“键”分段中展开“键类型”选项,在“基类”下拉菜单中将类型从“object”改为“Actor”。回到“黑板”面板,再次点击“新建”,这次选择布尔类型,把这个黑板键命名为“Has Line Of Sight”。

接下来,首先在内容浏览器中找到“AIC ThirPerson Character”然后打开它,接着创建一些辅助函数以便让黑板键处理起来更加容易。第一个函数有一个Actor输入,并会把某个黑板键设置为相同的Actor值,在“我的蓝图”面板中点击“函数”分段中的加号图标,新建一个函数,将函数命名为“Update Target Actor Key”。在细节面板中,点击“输入”分段中的加号,新建一个输入,选择“Actor”作为输入类型,将此输入命名为“Target Actor”。第一步是获取当前的黑板。右键事件图表,搜索“Get Blackboard”,选择“AI”>“变量”中的“Get Blackboard”。拖动“黑板”组件对象引用的引脚然后输入“Set value as Object”,这样会自动把黑板对象作为“Set value as Object”的目标参数。接下来,我们需要创建一个键名,它指向与行为树相关联的黑板中的黑板键。为此,我们拖动“Set value as Object”的“key name”,选择提升至变量,将这个新变量命名为“Target Actor Name”。保持选中状态,移到细节面板,找到类别面板,新建一个类别,在这个选项框中输入“Key Names”并以此命名。注意,这样会把我们的新变量自动归类到“我的蓝图”面板中的“Keys Names”类型。下一步是设置“Target Actor Name”的默认值,在此之前,我们需要编译蓝图。

 

编译后细节面板中“Target Actor Name”的默认值为无,将其设置为与黑板键名相同,即“Target Actor”。“Set value as Object”需要的最后一个参数就是传递给黑板的数值。这里就要用到我们此前创建的输入。将“Target Actor”连到“set values as object”的“object value”,把这个函数的执行引脚连到“Set value as Object”。

我们要创建的下一个函数拥有一个黑板键,它能保存AI当前能否通过感知系统观察到玩家。和之前一样,先在“我的蓝图”面板中新建一个函数,将它命名为“UpdateHasLineOfSightKey”,在细节面板的“输入”分段中,点击加号添加新的输入,确保这个输入是布尔类型,将这个新参数命名为“HasLineOfSight”。和之前的函数一样,我们首先要获得正确的黑板,右键点击事件图表,然后输入“Get Blackboard”,选择“AI”>”变量”中的函数,拖动这个黑板引用的引脚,然后输入“Set value as Bool”,拖动“Key name”变量,选择“提升为变量”,将其命名为“HasLineOfSightName”。 下一步是设置“HasLineOfSightName”的默认值,在此之前,我们需要编译蓝图。编译后细节面板中“HasLineOfSightName”的默认值为无,将其设置为与黑板键名相同,即Has Line Of Sight”。然后将两个函数引脚相连,将“Has Line Of Sight”输入引脚与“bool value”相连。

现在我们要回到角色的“on target perception updated”事件,然后使用这个时间来更新我们新建的黑板键。这意味着每当感知状态发生改变时,相关的黑板键也会更新。

在内容浏览器中找到“AICharacter1”,首先在触发“target lost”事件时,清空“target actor”黑板键。当前,这个事件会在目标超出视野5秒后触发,这表示AI完全遗忘了目标Actor,并放弃进行跟踪。为了访问我们刚刚创建的函数,我们首先要获取AI控制器的引用。右键点击事件图表,然后输入“Get Controller”,直到出现这个函数,这个函数会返回一个泛型控制器引用。我们需要将这个泛型类型转换为“AIC ThirdPerson Character”。为此,我们可以拖动返回值,输入“Cast”,选择“Cast to AIC ThirdPerson Character”。为了保证图表条理清晰便于理解,我们可以转换成纯类型转换,右键点击节点选择“转换为纯类型转换”。现在拖动“AIC ThirdPerson Character”引脚然后引用我们定义的函数即“Update Target Actor Key”,然后连接设置节点的执行引脚,如图所示:

 

此时,期望的黑板状态是让“target actor”的值为空,也就是现在没有target actor。为此,这个函数不需要提供任何参数。

让我们来看这个事件的另一种结果。我们需要使用“”line of sight”键来表示这种情况,我们利用函数把“HasLineOfSight”键设置为假,我们可以复制这两个节点“Get Controller”和“Cast to AIC ThirdPerson Character”,他们允许我们获得“AIC ThirdPerson Character”AI控制器。再次拖动“AIC ThirdPerson Character”引脚然后引用我们定义的函数即“update has line if sight key”, 然后连接设置节点的执行引脚,如图所示:

 

复制这三个节点“Get Controller”和“Cast to AIC ThirdPerson Character”和“Update Target Actor Key”,将他们的执行节点连接到“clear and invalidate timer by handle“。这个句柄当前连到分支的”真“值引脚,这种情况下我们需要提供”target actor“。所幸我们之前已经设置好了,找到”我的蓝图“面板,找到”PerceivedActor“,按住Ctrl键,左键点击它并拖到事件图表中,将”PerceivedActor“连到”target Actor“。”PerceivedActor“是之前在事件中定义的变量,我们获取了事件和感知系统提供的Actor,然后将”PerceivedActor“赋值给它,最后,复制上面这三个节点 “Get Controller”和“Cast to AIC ThirdPerson Character”和“update has line if sight key”,它们用于获取“update has line of sight key“函数,将他们连接到“Update Target Actor Key”。注意,分支的这个部分用于定义Actor刚刚被感知系统被感知到时的状态。这里要把“has line of sight“设置为真,勾选函数中的复选框。

让我们快速回顾一下做了那些修改。可以看到,这个“on target perception updated“事件为AI定义了三种不同状态。第一种状态,Actor被感知时,这个状态定义了AI看到Actor时的情况。第二种结果,返回值为”假“的结果,定义了看不到Actor时的状态。即使看不到,我们仍在黑板中保留了被感知Actor的值,这种状态表示AI记得看到了某个对象,只是当前看不到了。最后是”target lost“事件,它会在对象消失5秒后触发,这种状态表示AI当前看不到,当前感知的Actor并且对它丧失了兴趣。值得一提的是,我们之所以设置黑板键,就是为了提供信息,并通过黑板键将信息提供给行为,它不做任何决策,这由行为树决定。

下面我们在行为树中把所有这些修改内容拼合起来。我们将借助新的黑板键和装饰器,让AI有能力决定是追逐玩家还是继续随机漫游。首先,在内容浏览器中打开行为树资源“BT_EnemyAI“,我们将使用当前保存在黑板中的信息,在两个序列中二选一。删除第一个序列,拖动根节点,在菜单中选择”选择器“,把选择器连至现在的”随机漫游“序列。随机漫游序列的优先级比我们创建的序列要低。在行为树中执行顺序是从左到右。通过刚刚创建的选择器新建一个序列,在细节面板中的”描述“分段中,将节点名称改为”chase player“,拖动”chase player“序列,选择”move to task“,我们需要将AI移到目标Actor的位置,为此,在右侧细节面板中的”黑板“分段点击”黑板键“,在下拉菜单中选择”Target Actor“。”Target Actor“是我们创建的用于和函数一起更新的黑板键。接着,再次拖动追逐玩家序列,在”move to“节点的右侧新建一个节点,选择”Wait“节点,在细节面板的”等待“分段中,将等待时间五秒改为一秒。通常在任务结束后会添加一些等待任务,因为这能避免行为树在不同序列间快速循环,从而显得不自然。添加这两个序列后,”追逐玩家“序列基本完成了,考虑到行为树的执行顺序,这个新的分支会始终在随机漫游序列之前执行。

 

接下来,需要使用装饰器控制这个分支的执行方式,只有当前需要设置目标Actor时才执行它。右键点击,”追逐玩家“序列,选择”添加装饰器“>”黑板“。接下来,选中这个新的装饰器,在细节面板中的描述段将节点名称改为”is a target actor set“。我们来看看要使用哪些黑板键,由于我们关心的是目标Actor,所以应该在细节面板中”黑板“分段中,在”黑板键“下拉菜单中选中”SetActor“。接下来我们需要思考的是和键有关的是什么内容。”黑板“分段允许我们定义我们期望的结果。上面的”流程控制“分段允许我们控制观察到期望结果时执行流程会发生什么。”通知观察者“下拉菜单有两个选项,默认选项是”on result change“。每当键查询的结果发生变化时,我们会按照”observer aborts“描述的内容更改执行流程。

 

分类:

技术点:

相关文章: