UE学习记录:AI

今天要讨论Unreal中的AI系统,包括以下几个部分:
首先是NavigationMesh,它仅为我们的AI角色提供寻路数据,而且它基本上只是告诉AI他可以和不允许移动的地方。
然后是BehaviorTree(行为树 ),它基本上是AI的大脑,把它想象成一个基于节点的树,从上到下,从左到右执行,这是我们今天主要关注的内容。
还有BlackBoard,为AI提供数据存储,可以理解为AI的记忆,本身不运行任何逻辑。
环境查询系统EnvironmentQuerySystem,为AI进行空间查询,以弄清世界中靠近AI的物体,甚至是世界中一些适合做掩护的地方。
PawnSensing & AIPerception,为AI中加入类似于感觉的东西,比如说能够看到或听到玩家的声音。
还有两个调试工具,GameplayDebugger(游戏调试器)和VisualLogger(视觉记录器)。
对于行为树BehaviorTree。首先有个结点叫Sequence,它负责从上到下,从左到右按顺序运行,并取消“失败”的节点;然后是Selector,它将从左往右依次选择他的孩子节点。我们有三种方法来装饰BehaviorTree
task(比如Wait,MoveTo),它可以在多秒或多帧中被执行,比如这里的执行Wait 0.8秒,执行MoveTo直到抵达目的地。
Service,它会反复执行后台任务,像是这里的“Cancel others when in attack range”,重复对AI下指令以更新它的状态。
Decorator,它基本上是用于状态检查和流控制,返回true/false,比如这里的Cooldown节点,第一次触发这个节点它将被允许运行,而在第二次触发的时候如果冷却时间(Wait)没到,就不能运行,将会执行MoveTo。

由于每当我们添加一个新的类,编辑器就会试图进行热重载,所以在这里进行设置以解决这个麻烦,进入编辑器,编辑->编辑器偏好设置->所有设置->热重载->取消勾选

首先我们添加一个Character类,命名为RgAICharacter,可以删除这个类的组件绑定部分;再添加一个AIController类,命名为RgAIController,我们会将AI的行为写到AIController类中。在编辑器中创建一个AI的文件夹,在里面创建一个RgAICharacter类的蓝图,命名为BP_MinionRanged,设置Mesh和动画后把AI放到场景中。添加导航网格数据,它可以使得AI在碰到障碍物时能够调整移动,我们在左边的放置Actor一栏搜索nav mesh bounds volum,把它拖进场景,如果它不可见,可以在显示中勾选导航或者按P键。
右键->人工智能->行为树,命名为BT_MinionRanged;右键->人工智能->黑板,命名为BB_MinionRanged。在黑板中我们可以选择我们想保留的数据,然后在行为树中我们可以制作执行逻辑。在行为树中指定使用的黑板,然后到黑板中添加数据,我们添加一个向量类型的新键,命名为MoveToLocation,然后到行为树中执行实际的移动,我们从根的下拉列表里选择Sequence,在Sequence下拉列表的tasks中选择MoveTo(MoveDirectlyToward会忽略导航),细节->背景->黑板键,选择MoveToLocation,这样就为行为树分配了黑板来使用MoveTo了。另外,在Sequence下拉列表的tasks中选择Wait,这样在MoveTo执行完后,可以等待设定时间,默认设置为5s。
现在我们可以进入RgAIController类中实现MoveTo的逻辑。首先我们重写BeginPlay,调用Super确保其基本的逻辑。然后,我们调用包含在AIController中的RunBehaviorTree,这里指定的UBehaviorTree*是一个变量,我们把它变成一个资产,暴露给蓝图:
在编辑器中创建RgAIController类的蓝图,命名为BP_MinionController,AI设置里的行为树选择BT_MinionRanged,然后到AI角色蓝图里,细节->Pawn->AI控制器类,选择BP_MinionController,这就是它实际上将产生的类,打开行为树BT_MinionRanged,模拟运行就能看到它的执行情况,所有的步骤都是执行的,但目前AI角色没有移动,是因为还没有设置MoveToLocation的值,我们到RgAIController.cpp中添加如下代码:
这样一来AI就会走到玩家出生的地方,但AI只会移动一次,玩家离开出生点后AI并不会继续追踪玩家,这是由于MoveToLocation在玩家生成时,只被赋值了一次,所以行为树每次更新MoveTo获取的MoveToLocation都是同一个数值。要实时追踪玩家的位置,首先进入黑板,添加object类型的新键命名为TargetActor,指定它的基类为Actor,并在行为树的MoveTo中将原来的黑板键MoveToLocation指定为TargetActor,然后到RgAIController.cpp中为其进行设置。
游戏运行时,按下“;”键可以打开游戏调试器,我们可以看到相关的信息,比如人物类别,控制器实例,行为树,当行为树足够复杂的时候,我们可以对节点进行自定义注释或者命名,可以使其在调试的时候更容易阅读。