使用EQS在敌人附近移动
2023年11月6日 2024年1月11日
说明
AI / EQS / Context
完成两点
- 在敌人周围生成具有随机性的点阵, 选择一个位置点, 去到那里
- 设置点阵中心为敌人
生成创建BP类
Content/AI/EQS目录下, 创建EQS资产EQS_NextToEnemyLocation
为EQS_TestPawn设置EQS模板: 在世界大纲中选中EQS_TestPawn, Details > EQS > Query Template
, 设置为EQS_NextToEnemyLocation
设置EQS资产
EQS_NextToEnemyLocation
-
添加生成器: 环形点阵
-
设置环形点阵
- Projection Data > Track Mode Navigation Inner Radius Data Binding = None, Inner Radius = 450 Outer Radius Data Binding = Random number, Outer Radius = 1000-1500 Number Of Rings Data Binding = Random number, Number Of Rings = 3-8 Points Per Ring Data Binding = Random number, Number Of Rings = 4-20 Arc Angle 360 Use Spiral Pattern 勾选 -
为环形点阵添加距离条件: Distance
-
设置Distance
- Filter > Filter Type Range: 400-800 Score > Scoring Factor Data Binding = Random number, Scoring Factor = -1 ~ 1, 随机
使用蓝图类测试
创建蓝图类
- | |
---|---|
基类 | EnvQueryContext_BlueprintBase |
路径 | AI/EQS |
名称 | EQS_ContextSTUCharacter |
覆写函数
选择返回Actor或者位置
双击打开 EQS_NextToEnemyLocation
选择函数原型
My Blueprint > Functions Override
, 选择 Provide Single Actor
- | |
---|---|
Provide Actors Set | Actor数组 |
Provide Locations Set | 位置数组 |
Provide Single Actor | 单一Actor |
Provide Single Location | 单一位置 |
覆写
-
筛选Actor类型
Provide Single Actor
之后, 添加节点:Get All Actors Of Class
, 设置类类型为STUBaseCharacter -
Get All Actor Of Class
之后, 返回第一个元素, 添加节点:Get (a copy)
未作检查, 返回第一个元素
设置中心点
-
设置环状点阵生成器中心点使用EQS_ContextSTUCharacter
-
设置Distance距离计算参照点使用EQS_ContextSTUCharacter
-
查看
-
在场景中添加BP_STUBaseCharacter
-
移动游戏角色, 再次选中TestPawn, 环状点阵的中心一直是游戏角色
-
移除游戏角色
-
在行为树中使用
-
选择
Run EQS Query
, 设置使用的模板为EQS_NextToEnemyLocation
Details > EQS > Query Template
, 选择EQS_NextToEnemyLocation -
运行游戏
NPC始终在游戏角色附近的圆环点阵中切换位置
学习EnvQueryContext_Querier
- 构造函数
- PrivideContext
- 该函数只用来计算Actor, 返回计算得到Actor
- 获取EQS上级, 并通过SetContextHelper设置给ContextData
- 我们要做的, 即获取黑板变量EnemyActor对应的Actor, 并设置给ContextData
- QueryOwener: Pawn或者Character, EQS的上级
- 该函数只用来计算Actor, 返回计算得到Actor
使用C++类实现
设置黑板变量EnemyActor
创建C++类
- | |
---|---|
EnvQueryContext | |
STUEnemyEnvQueryContext | |
AI/EQS | |
Public |
修改STUUtils.h的预编译命令的遗留错误
ShootThemUp: STUUtils.h
1#pragma once
修改头文件搜索路径
ShootThemUp: ShootThemUp.Build.cs
1PublicIncludePaths.AddRange(new string[] 2{ 3 "ShootThemUp/Public/Player", 4 "ShootThemUp/Public/Components", 5 "ShootThemUp/Public/Dev", 6 "ShootThemUp/Public/Weapon", 7 "ShootThemUp/Public/UI", 8 "ShootThemUp/Public/Animations", 9 "ShootThemUp/Public/Pickups", 10 "ShootThemUp/Public/Weapon/Components", 11 "ShootThemUp/Public/AI", 12 "ShootThemUp/Public/AI/Tasks", 13 "ShootThemUp/Public/AI/Services", 14 "ShootThemUp/Public/AI/EQS" 15});
实现STUEnemyEnvQueryContext
添加属性: EnemyActor变量名
protected
ShootThemUp: AI/EQS/STUEnemyEnvQueryContext.h
1UPROPERTY(EditAnywhere, BlueprintReadWrite) 2FName EnemyActorKeyName = "EnemyActor";
覆写虚函数
public
ShootThemUp: AI/EQS/STUEnemyEnvQueryContext.h
1virtual void ProvideContext(FEnvQueryInstance &QueryInstance, FEnvQueryContextData &ContextData) const override;
-
获取EQS上级对应的Actor
FEnvQueryInstance在EnvQueryTypes.h中
1#include "EnvironmentQuery/EnvQueryTypes.h" 2 3const auto QueryOwner = Cast<AActor>(QueryInstance.Owner.Get());
-
获取黑板组件
通过转换EQS上级得到Pawn, 通过Pawn得到Controller; 指定组件类型, 通过Controller获取黑板组件
1#include "Blueprint/AIBlueprintHelperLibrary.h" 2#include "BehaviorTree/BlackboardComponent.h" 3 4const auto Blackboard = UAIBlueprintHelperLibrary::GetBlackboard(QueryOwner); 5if (!Blackboard) return;
-
获取黑板变量
1const auto ContextActor = Blackboard->GetValueAsObject(EnemyActorKeyName);
-
将黑板变量用作中心点
1#include "EnvironmentQuery/Items/EnvQueryItemType_Actor.h" 2 3UEnvQueryItemType_Actor::SetContextHelper(ContextData, Cast<AActor>(ContextActor));
-
完整实现
ShootThemUp: AI/EQS/STUEnemyEnvQueryContext.cpp
1#include "EnvironmentQuery/EnvQueryTypes.h" 2#include "Blueprint/AIBlueprintHelperLibrary.h" 3#include "BehaviorTree/BlackboardComponent.h" 4#include "EnvironmentQuery/Items/EnvQueryItemType_Actor.h" 5 6void USTUEnemyEnvQueryContext::ProvideContext(FEnvQueryInstance &QueryInstance, FEnvQueryContextData &ContextData) const 7{ 8 const auto QueryOwner = Cast<AActor>(QueryInstance.Owner.Get()); 9 10 const auto Blackboard = UAIBlueprintHelperLibrary::GetBlackboard(QueryOwner); 11 if (!Blackboard) return; 12 13 const auto ContextActor = Blackboard->GetValueAsObject(EnemyActorKeyName); 14 UEnvQueryItemType_Actor::SetContextHelper(ContextData, Cast<AActor>(ContextActor)); 15 16}
使用C++类STUEnemyEnvQueryContext
设置行为树
BT_STUCharacter
-
在环形点阵和距离限制条件中使用STUEnemyEnvQueryContext
-
恢复行为树框架, 移除Task
-
添加任务: RunEQSQuery - EQS_NextToEnemyLocation
-
添加任务: RunEQSQuery - EQS_RandomRoam
-
暂时移除Fire服务里目标: 点击恢复图标
查看
-
按下
'
打开调试界面 -
选中AICharacter
-
按下小写键盘
3
显示EQS -
当前存在两个EQS点阵, 按下小写键盘
*
显示当前EQS
Project Settings > Engine > Gameplay Debugger
对于EQS的使用, 我们现在可以设置任意移动模板, 或者随机结合他们
- 可以移除楼梯和模拟爆炸
- 可以添加墙, 躲避NPC捕获