UE5——AI追逐(蓝图行为树)
Posted 乔安鱼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UE5——AI追逐(蓝图行为树)相关的知识,希望对你有一定的参考价值。
使用蓝图和行为树完成一个AI看到玩家后进行追逐的效果,关于如何制作AI、寻路设置、行为树等这些在随机漫游里都有记录。
一、AI原理
AI的处理过程可以分为三大阶段:感知——思考——行动
(1)感知
对AI当前状态作记录。
“基本过滤”也是一种感知行为。
基本过滤 - 如果其他感知的优先级更高,会忽略部分信息
(2)思考
AI利用感知阶段收集到的信息,对当前信息和目标进行评估,为之后的行动指明方向。
(3)行动
根据感知阶段的信息和思考阶段的决策,AI在行动阶段对信息做出相应的行为。
行动阶段结束后,AI会再次回到感知阶段。
行为有可见的,如跳跑;也有不可见的,如通信。
制作的方法围绕着这个原理:
1.感知——给与AI视觉感官,AI看到玩家。
2.思考——AI在角色蓝图进行决策,并通过控制器将感知到的数据通过黑板传给行为树。
3.行动——行为树决定AI是否追逐玩家。
二、AI感知
设置好AI角色蓝图、控制器蓝图、寻路后,就可以开始制作AI追逐了,随机漫游的部分可做可不做。
(一)添加视觉
1.创建视觉感官
为AI增加AI感知组件:打开AI角色蓝图 - 在组件面板增加AI perception感知组件
- 感官配置 - 多少数组代表AI拥有多少感官
细节 - AI感知,在感官配置栏添加数组 - 数组类型选AI sight Config(AI视力配置)
2.按归属检测 -勾选“检测中立方”
- 系统默认为中立,所以给玩家选为中立方以便检测
- 最大年龄 - 与多久前见到的最后一个目标有关
3.把玩家标记为刺激源
这样AI就能感知到,不然AI看不到玩家。
打开玩家角色蓝图 - 在组件面板添加AI感知刺激源组件。(不要选成感知组件了)
细节面板 - AI感知 - 勾选“自动注册为源”、添加数组、类型为AISense_Sight
(二)Gameplay调试感官
给AI设置好视觉后,我们还要在Gameplay中调试感官是否能够正常感知到玩家。
在使用Gameplay调试器之前,先禁用AI蓝图事件让AI停止移动,这样有助于处理感知系统。(如果做了随机漫游要断开,没做可以不用管)
1.停止AI移动
打开AI蓝图 - 对“事件开始运行”的引脚按Alt断开,停止调用随机漫游事件
2.关闭TAA临时抗锯齿选项
编辑 - 项目设置 - 引擎 - 渲染 - 默认设置 - 抗锯齿方法,勾选“无”
(其实不开也没什么问题)
- TAA临时抗锯齿 - 会把若干帧混合在一起,Gameplay的调试线条这类单像素线条很难观察到。
3.调试感官
运行游戏 - “‘”调出控制台 - 4打开感知信息
- Sight:1 - 可被看见
- Age:多久前更新的信息
【0】 - 最新的信息。
离开后,年龄开始增加。球体表示最后的位置。
在AI蓝图中调整视线半径和失去视线半径数值。
- 视线半径 - 进入绿圈即可获得视野。
- 失去视线半径 - 走出粉圈则失去视野。
- 两者有间隔:过渡更自然。
- 两者重合:会在边界处反复失去和获得视野。
三、AI决策
当AI视觉感官启动后,需要提供感知信息给AI,让AI制定决策。修改行为树以便控制执行流程。
(一)创建辅助函数
在制作蓝图前,还有两个步骤:
- 在黑板中创建两个条目——存储感知信息
- 在控制器蓝图中创建两个辅助参数——以便在角色蓝图中调用。
1.创建新的黑板键来保存信息
一共创建两个黑板键:
- 目标Actor——AI将向这个Actor移动。
- 是否看见玩家——用于行为树进行判断,如果没看见将进行其他的动作。(更多的是辅助判断,嫌麻烦可以不做这个)
打开AI行为树 - 黑板 - 新建条目object类型,命名Target Actor。
细节面板,键类型>基类,改为Actor类型。
新建布尔类型条目,命名Has Line Of Sight。
两个黑板键都创建好了。
2.更新目标Actor函数
打开AI控制器蓝图,因为玩家不断地在移动,所以要更新“目标Actor”的值。
在“我的蓝图”面板中新增函数,命名为“Update Target Actor Key”。
在细节面板,输入分段添加一个条目。类型为Actor,命名为Target Actor。
蓝图中新建一个变量“获取黑板键Get Blackboard”。
拖拽引脚新建函数“Set Value As Object 将值设为对象”,拖拽Key name提升为变量“Target Actor Name”(与行为树相关联的黑板键相同)。
细节面板>变量>类别,新建一个类别Key Names.
设置Target Actor Name的默认值:需要与黑板键名字一致,最保险的方法就是复制粘贴。
默认值一定要和黑板键名字一样,不然值会传导错误。
打开黑板,复制Target Actor名字,粘贴到Target Actor Name的默认值。
Update Target Actor Key的Target Actor 引脚与Set Value As Object的Object Value相连,执行引脚相连。
3.保存是否看见玩家函数
行为树要时刻判断是否看到玩家以决定下一步动作,所以这个值也需要更新。
依旧是控制器蓝图,在我的蓝图面板中新增函数,命名为Update Has Line Of Sight Key。
在细节面板,输入分段添加一个条目。类型为Boolean,命名为Has Line Of Sigh。
接下来制作方法同上:
蓝图中新建一个变量“获取黑板键Get Blackboard”。
拖拽引脚新建函数“Set Value As Bool 将值设为布尔”,拖拽Key name提升为变量“Has Line Of Sight Name”(与行为树相关联的黑板键相同)。
移入Key Name类别。
设置Has Line Of Sight Name的默认值:
打开黑板,复制Target Actor名字,粘贴到Target Actor Name的默认值。
Update Has Line Of Sight Key的Has Line Of Sight 引脚与Set Value As Bool的Bool Value相连,执行引脚相连。
(二)创建蓝图进行决策
接下来在AI角色蓝图中编写:
- 对信息进行判断——根据不同的情况,传递不同的信息。
- 传递感知信息——把感官看到的信息传递给控制器,再通过黑板传递给行为树。
1.判断是否看到玩家
在AI蓝图中,选取AI Perception组件。
在细节面板的事件选项中添加“On Target Perception Update目标感知更新时”事件。
- On Target Perception Update事件 - 捕获并存储AI感知的信息以及感知的方式。
- Actor - 这个变量包含AI感知到的Actor的引用。这个引用会在蓝图中频繁地使用。
拖拽Actor引脚,提升为变量并给改名为“Perceived Actor可被感知的Actor”。
拖拽Simulates刺激源结构引脚,添加“中断AI Simulates”断点。
(中断感知并对此刻的信息进行判断)
左键点击并按住B生成Branch分支节点 - 中断AI Simulates的Successfully Sensed布尔值引脚与分支节点的“条件Condition”连接,SET的执行引脚与分支节点的执行相连接。
- 收起引脚 - 在中断AI Simulates的细节面板中点击“隐藏未连接的引脚”
完整如下:
2.丢失视野,则AI放弃追踪。
当追到一半时,玩家丢失,AI要放弃追踪。
(这个情况与未看到玩家逻辑相似)
右键创建一个“自定义事件Custom Event”并改名为“Target Lost目标丢失”。
拖拽分支的False引脚并连接新建一个事件定时器“Set timer By Event”。
Target Lost事件与定时器的Event相连接,作为触发器,time设为5s。
不要勾选循环,因为只触发一次。
(丢失玩家5s后,放弃追逐)
在“我的蓝图”面板按住Alt键,拖动Perceived Actor到蓝图中创建一个变量。
Target Lost与Set执行引脚相连。
(由于没有为Perceived Actor赋值新的变量,AI感知的对象会被清空,即无追逐对象)
为真时,消除定时器
拖拽分支的True引脚并新建一个函数“Clear and invaliate timer by handle以句柄清除定时器并使之无效”。
在定时器的返回值拖拽并提升为变量,改名为Target Lost Timer。
在我的蓝图面板按Ctrl拖拽并创建Target Lost Timer变量,与以句柄清除定时器并使之无效的handle句柄引脚相连接。
完整如下:
3.丢失玩家/未看到玩家
AI根据观察到的信息判断后对目标Actor进行了设置,但是行为树并不知道AI是否看到玩家,所以还要通过我们之前设置的辅助函数将信息传递给行为树进行判断。
新建get controller函数 - 把泛型引用改成AIC_ThirdPersonCharacter:拖拽get controller的返回值,新建cast to AIC_ThirdPersonCharacter“类型转换成AIC_ThirdPersonCharacter”。
为了清晰便于理解,“类型转换成AIC_ThirdPersonCharacter”右键“转换成纯类型转换” 。
拖拽As AIC_ThirdPersonCharacter引脚调用Update Target Actor Key。
Target Lost连接设置节点的执行引脚与Update Target Actor Key的执行引脚相连。
(当没有目标Actor时,Update Target Actor Key不会提供任何参数)
利用函数把Has Line Of Sight Key设为假:
复制get controller、类型转换成AIC_ThirdPersonCharacter两个函数。
拖拽As AIC_ThirdPersonCharacter引脚调用Update Has Line Of Sight Key。
连接设置节点的执行引脚与Update Has Line Of Sight Key的执行引脚相连。
(避免Update Has Line Of Sight Key勾选Has Line Of Sight)
4.看到玩家
制作方法同上。
为真时的执行引脚与Update Target Actor Key的执行引脚相连。
在我的蓝图面板ctrl拖拽Percevied Actor 函数赋值给Update Target Actor Key的Target Actor。
Update Target Actor Key的执行引脚与Update Has Line Of Sight Key 的执行引脚相连,勾选Has Line Of Sight。
总结
整个角色蓝图的逻辑如下:
玩家作为ACTOR刺激源,当玩家在AI的视野内变化位置时,AI视觉感官将中断刺激源,并对当前情况进行判断。
- 有Actor,为真——消除定时器,是否看到玩家为真,Actor作为目标Actor,并将这两个信息通过辅助函数传递给控制器,控制器再传递给行为树。
- 无Actor,为假——设置定时器,是否看到玩家为假。5s后触发丢失玩家事件,目标Actor为空。并将这两个信息通过辅助函数传递给控制器,控制器再传递给行为树。
四、拼凑行为树
到这一步,已经做完了大部分内容,接下来对行为树进行一个组装就可以结束了。
1.追逐行为
打开行为树 - 第一个合成器换成Slector ,随机漫游放置在右侧。
在选择器下创造一个新序列Sequncer,并改名为“追逐玩家”。
追逐玩家序列下新建Move to任务,并在细节>黑板>黑板键,改为Target Actor。
新建Wait任务,并把时间改为1s。
- Wait任务 - 通常会在序列后加一个1s的wait任务,以此来避免AI在多个序列中快速浏览,这样会自然一些。
2.装饰器判断是否追逐
AI还要进行判断,是否要追逐玩家,如果不追逐则进行其他行为。
使用装饰器控制分支的执行方式(只有当前需要设置目标Actor时才应该执行):
追逐玩家序列器>右键>添加装饰器>BlackBoard。
装饰器起名为Is A Target Actor Set?,把节点名称描述得清楚一些,有助于理解。
配置装饰器,控制执行流程:黑板键选取Target Actor,通知观察者选取结果改变时、观察器中止选取Both
a.黑板分段 - 允许定义期望的结果
b.流控制分段 - 允许控制观察到期望结果时,执行流程会发生什么。
- 通知观察者
【结果改变时】 -(默认)键查询结果变化时,会按照观察器中止的内容执行。
【值改变时】 - 当目标Actor键变化时,执行流程改变。
- 观察器中止
【None(默认)】 - 不中止任何操作
【Self】 - 中止自己
【Low Priority】 - 中止低优先级序列
【Both】 - 两个序列都中止
总结
游戏开始后,AI行为树从左到右进行选择:
1.追逐玩家?
根据黑板传递来的目标Actor进行判断,设置了Actor,则向该Actor移动,到达后停顿1s,再进行下一次选择。
如果未设置Actor,或Actor改变,则进行下一个行为。
2.随机漫游
AI获得一个随机点,向该点移动,达到后停顿3s。
可见是否看见玩家的黑板值并未在行为树中起到作用,在角色蓝图中也未起到重要作用,只是一种辅助作用。
目标Actor起到了重要作用,角色蓝图、装饰器都根据此进行判断,更是move to的目标点。
以上是关于UE5——AI追逐(蓝图行为树)的主要内容,如果未能解决你的问题,请参考以下文章