7 - AI入门

本文将初步介绍UE5中有关人工智能系统的入门知识,例如AI控制器AIController,黑板Blackboards和行为树的概念及简单使用。

AI Controller

PlayerControllerAIController这两个Actor类都继承自AController基类,AController可以用来控制Pawn或者Character的动作。玩家控制器依赖于实际玩家的输入,而AI控制器通过运用人工智能来操控其拥有的角色,并根据设定好的规则对环境作出反应。一个AI控制器可由相同AI Pawn的多个实例使用,并且相同的AI控制器可在不同的AI Pawn类中使用。

主动拥有Pawn

在C++中,可用Possess()来拥有一个Pawn:

void AController::Possess(APawn* InPawn);

可用UnPossess()解除Pawn的拥有状态:

void AController::UnPossess();

在调用Possess()UnPossess()的同时,也会触发OnPossess()OnUnPossess()回调。

导航网格体 NavMesh

UE5通过导航网格体NavMesh告诉人工智能哪些环境是可导航的,而哪些环境是不可导航的。UE5还支持动态的NavMesh,它支持动态对象在环境中移动时实时更新NavMesh,这使得AI能够识别环境变化,并适应导航路径。

在引擎中拖入一个NavMesh,让它和地面相交,然后按下P键启用导航Debug视图,出现的绿色便是可导航的区域。效果如下:

RecastNavMesh

在创建NavMesh的同时,一个名字为RecastNavMesh-Default的Actor被自动创建。这个RecastNavMesh可以被视为NavMesh的“大脑”,它包含了调整NavMesh所需的参数,这些参数将直接影响AI如何在给定区域中导航。

RecastNavMesh包含的参数很多,常用到的参数如下:

  • 显示 Display:影响可视化调试NavMeshBoundsVolume生成的导航区域,方便debug。
  • 生成 Generation:决定NavMesh如何生成,以及确认哪些区域是可导航的,哪些不是。常用到的参数如下:
    • Cell Size:NavMesh在给定空间中生成可导航区域的精度;
    • Agent Radius:在此区域导航的Actor的半径。
    • Agent Height:在此区域导航的Actor的高度。
    • Agent Max Slope:游戏世界中可能存在的倾斜角度。
    • Agent Max Step Height:AI可以导航到的台阶高度,以楼梯台阶为单位。

行为树和黑板

行为树和黑板协同工作,允许AI遵循不同的逻辑路径,并根据各种条件和变量做出决策。

黑板

黑板是定义变量(也被称为键Key)的地方,方便行为树使用这些变量做决策。

行为树

行为树是一种可视化编程工具,可以根据某些因素和参数告诉Pawn该做什么。它由一组对象组成,即 组合器(Composites),任务(Tasks),服务(Services)和装饰器(Decorators),它们共同定义AI将如何根据设置的条件和逻辑流程进行行为响应。

组合器 Composites

组合器节点告诉行为树如何执行任务和其他操作,也能附加装饰器和服务,以便在执行行为树分支前应用可选条件。

常见的组合器节点如下:

  • Selector:Selector节点按从左到右的顺序执行其子任务,并在其中一个子任务成功时停止执行之后的子任务。

    此外,能在节点右上角处发现数字,这是节点的执行顺序,一般是从上到下、从左到右。

  • Sequence:Sequence节点从左到右顺序执行其子任务,当其中一个子任务失败将停止执行之后的子任务。

  • Simple Parallel:可同时执行任务和新的独立逻辑分支。例如下图,Wait任务执行的同时Sequence也在执行:

    在“细节”面板中可以调节该节点的Finish Mode参数:

    • Immediate:该节点将在主任务完成后成功完成。例如上图,Wait任务完成后后面的Sequence会自动停止。
    • Delayed:该节点将在主任务和后面的任务完成后才成功完成。

任务 Tasks

这里提供AI可以完成的任务,UE5默认内置了一些任务,包括移动到特定位置,旋转以面对目标,发射武器等。也能通过在蓝图或C++中创建自己的任务。

例如下图中定义了一个任务,从ReceiveExecuteAI事件开始,基于AI自己Pawn的位置随机生成一个新位置,然后在FinishExecute结束,并返回是否成功。

装饰器 Decorators

装饰器是可以添加到任务或组合器的条件,通常用于实现分支逻辑。除了使用内置的装饰器外,也能通过蓝图自定义装饰器。

服务 Services

和装饰器比较相似,也能添加到任务或组合器间,但服务允许我们基于它定义的间隔执行节点分支。

要想运行行为树,可在AIController中的BeginPlay中调用RunBehaviorTree:

实践

接下来尝试实践一下,实现AI按巡逻点寻路的功能。

首先,新建一个基于Actor的蓝图类BP_AIPoints,用于存储巡逻点。在这个类上新建一个vector数组Points,勾选“实例可编辑”和“显示3D控件”。然后新建一个函数GetNextPoint,用于在Points中获取一个巡逻点,这个巡逻点是本地坐标的,因此要转换为世界坐标:

然后将这个蓝图类放到地图上,在细节面板中添加数个巡逻点,然后在地图上摆好:

接下来要让敌人的蓝图类引用这个巡逻点实例,新建一个PatrolPoints变量,引用BP_AIPoints,别忘了勾选实例可编辑。然后在地图上点击敌人,绑定引用变量。接下来实现敌人的行为树:

其中找到巡逻点的函数如下:

最后编译好蓝图就行了。

参考资料

  • 中文翻译:《UE5 C++ 游戏开发完全学习教程》

  • 英文原版:《Elevating Game Experiences with UE5》