第五章 Enemy AI
2-Perparing Enemy For Combat(为战斗准备敌人)
- 现在我们主要解决两件事,一件是AI控制器,一件是行为树

- AI拥有AI避障、AI感官、设置团队ID区分敌我

- 行为树要讨论的事件

- AI控制器要讨论的事件

- 在讨论AI回避之前,为了让它正常工作,我们必须获取其中的一个属性

- 为了回避功能正常,我们需要准确反应胶囊体半径,将之前调过胶囊体的大小恢复成默认,网格尺寸调整就行,调胶囊体尺寸要调整他的高与宽,不要使用缩放



3-Crowd Following Component(人群跟随组件) ps.这集理论避障
- AI回避的构建方法两种

- RVO(反向速度障碍)避障的两种方法
- 使用代理远离彼此:使用次方法会忽略障碍物和导航网格,因此当在移动的时候,AI很可能脱离导航网格边界体积,导致卡在某个位置


- Detour Crowd Avoidance(绕道人群回避)
- 该方法知道其他的代理,会生成一条新的路径来绕过彼此,而且还知道我们导航网格的大小

- 新建一个AI控制器,然后重写这个组件类,因此我们不需要使用这个新的路径跟踪组件,而是需要使用的他的子类,这意味着,我们需要重写WarriorAIController类中的此类




- 然后创建一个子蓝图添加到敌人身上


4-AI Perception
- 添加感官系统
- 头文件
- #include “Perception/AIPerceptionComponent.h”
- #include “Perception/AISenseConfig_Sight.h”


- 委托函数的参数变量是从这里来的


5-Generic Team ID
- 设置团队编号,重写IGenericTeamAgentInterface接口中的GetTeamAttitudeTowards函数,这里这个函数记得加Override


- 然后在角色控制器中设置角色的团队属性,这里这个函数记得加Override


- 最后在AI感官更新信息的回调函数中测试一下信息


6-Behavior Tree
- 行为树,这节内容不怎么多,看看即可

7-Configure AI Avoidance(配置AI避障)ps.这集需要多研究
- 使用
AI.Crowd.DebugSelectedActors 1
命令可以查看避障调试绘图
- 新建三个变量用来控制AI避障状态

- 在BeginPlay中设置,避障的参数

- 这几个参数与回避质量最相关的值,具体每个参数的作用看视频,上面这个数组对应我们代码中的那四个质量,我们使用最高质量所以调节Index[3],这里设置为0,当AI到达不了角色位置就会停下来



8-Behavior Tree Node Types
- 虽然绕道回避设置很不错了,但它仍然不能神奇地解决我们在战斗中可能遇到的所有问题。

- 这节课就写了一个获取玩家距离敌人的服务蓝图任务


9-Observer Aborts(观察中止 )
- 首先讨论两个问题,一个是是否进入扫射,一个是判断自己是否离角色远了

- None:无
- Self:当结果为假时中止自己
- Lower Priority:当结果为真时,中止其他优先级低的分支
- Both:以上两点都有

- 具体看视频
10-Orient To Target Actor(瞄准目标Actor)
- 新建一个BTService类来瞄准目标Actor

- UBTService_OrientToTargetActor.cpp
#include "AI/BTService_OrientToTargetActor.h"
UBTService_OrientToTargetActor::UBTService_OrientToTargetActor()
{
NodeName = TEXT("Native Orient Rotation To Target Actor");
INIT_SERVICE_NODE_NOTIFY_FLAGS();
RotationInterpSpeed = 5.f;
Interval = 0.f;
RandomDeviation = 0.f;
InTargetActorKey.AddObjectFilter(this, GET_MEMBER_NAME_CHECKED(ThisClass, InTargetActorKey),
AActor::StaticClass());
}
void UBTService_OrientToTargetActor::InitializeFromAsset(UBehaviorTree& Asset)
{
Super::InitializeFromAsset(Asset);
if (UBlackboardData* BBAsset = GetBlackboardAsset())
{