斯坦福UE4C++课程P39-P41基础AI与行为树
首先介绍AI基本概念:行为树、黑板、EQS
行为树是UE中AI做出选择的依据,其他AI系统还有utility AI和gope。
对于虚幻AI系统:
Navigation Mesh:Provides data on where AI is allowed to move (Path Finding)
Behavior Tree:'Brains' of AI. Tree executing from top-to-bottom and left-to-right
Selector,Sequence
Task,Service,Decorator
Blackboard:‘Memory’ of AI. Data storage,no logic
Environment Query System:Spatial queries for finding objects/locations based on 'tests'
PawnSensing & AIPerception:'Senses' to see or hear others
Debugging Tools
Gameplay Debugger (in-game:撇号键)
Visual Logger (Window > Developer Tools > Visual Logger)
Selector:从左至右选择一个子节点执行(先检查装饰器Decorator看是否能够执行)
Sequence:从左至右执行一系列子节点(cancel sequence on any ‘failure’)
Task,Service,Decorator:Task是AI动作(比如attack、move to...),Service重复执行背景任务(background tasks),Decorator装饰器可以用来检查条件、流程控制(返回true/false)
行为树节点:
接下来我们新建一个character类和AIController类,放在public/AI文件夹下。
AIController类类似于AI的大脑,我们将添加行为树到AIController类中
在AIController中添加行为树组件
在BeginPlay函数中:
运行行为树之后,我们获取到当前游戏编号为0的Pawn角色,把黑板的名为MoveToLocation的键赋值为Pawn的位置。
tip:有的函数第一个参数是const UObject* WorldContextObject,因为这是在静态类中的函数,没有上下文,需要传进去一个指定它在哪里被调用的对象,一般用this就行。
接下来在UE编辑器创建好AI角色蓝图、行为树、黑板、继承自新建C++AIController的AI控制器蓝图。
现在运行游戏,AI会移动到玩家出生点位置。
下面在黑板新建一个Object,父类选为Actor,命名TargetActor。行为树的MoveTo节点换为TargetActor。由于MoveTo节点每帧调用, 所以AI将一致追寻玩家,直到追到为止。我们在C++的BeginPlay函数中添加
将TargetActor键绑定为玩家。
现在编译运行游戏,AI追寻玩家直到追到为止。

当MoveTo节点执行完毕后,将执行Wait5秒,然后返回行为树的Root,重新执行MoveTo。
tip:可以使用回车键左边的撇号键在游戏运行时开启Debug界面


现在我们想让AI只有距离玩家有限范围时才追寻玩家
我们使用BTService继承的C++类SBTService_CheckAttackRange。
使用父类的TickNode函数。现在直接编译,会报无法解析符号的错,解决办法是到项目构建文件ActionRogueLike.Build.cs里添加‘GameplayTasks’模块。另外,在.uproject文件我们看到‘AIModule’模块已经被加入到项目,但为了保险起见,我们把该模块也加入到.cs文件里。
现在编译通过。
.h文件,新建了一个黑板键选择器和TickNode函数
.cpp文件,检查目标actor是否在AI的2000距离范围内,来决定是否要追寻玩家
现在编译,回到黑板新建WithinAttackRange布尔变量,保存,在行为树MoveToSequence节点右键选择Add Service,选择CheckAttackRange。
给Move To Player节点添加装饰器,类型选择Blackboard,键选择WithinAttackRange。

根据我们的需求,调整节点如下:

selector节点从左到右检查能够执行的首个节点来执行
现在只要玩家在范围内,就会一直移动到玩家位置(不会向右执行了),否则等待5秒后返回根节点root继续判断。
我们点击装饰器,把observer aborts选为self,表示当条件改为true时,将中止装饰器所在节点及所有子节点的执行,返回false,selector执行wait,当玩家再次不在范围时,条件变为true,selector继续执行move to player。
所以现在的效果是,AI移动到离玩家2000距离就会停止。

现在,只根据距离来判断让AI过于强大,因为如果AI和玩家隔了一堵墙,在根本看不见玩家的情况下仍可以追寻玩家,所以我们给AI添加视线追踪。
现在,如果AI看不到玩家,就算在范围内,仍会追寻玩家直到有视线为止。

