使用EQS寻找生命补给
2023年11月7日 2024年1月11日
说明
AI / EQS / Find Health Pickup
概览
- EQS生成器
- 生成器限制条件
- 使用C++实现Decorator
暂时修改生命补给外观
EQS标记也是亮色
-
Content > Materials
目录下选中M_BaseColor
-
选择关卡中的BP_STUHealthPickup, 通过Details面板在蓝图编辑器中打开
BP_STUHealthPickup
-
选中
Static Mesh
, 应用材质 -
回到关卡编辑器, 按住
Option
拖动BP_STUHealthPickup进行复制, 共三个 -
在场景中添加墙
Place Actors > Geometry > Box
-
设置墙; 将一个生命补给放在墙后
Details > Brush Settings
, 设置X = 50, Y = 500, Z = 500
创建EQS资产
Content/AI/EQS
目录下, 新建EQS资产, 命名为EQS_FindHealthPickup
添加生成器, 寻找场景中指定类型的Actor
Generators > Actors Of Class
- | ||
---|---|---|
Searched Actor Class | 指定Actor类型 | STUHealthPickup |
Search Radius | 搜索半径 | 1500 |
设置场景中EQS_TestPawn使用的EQS模板
Details > EQS > Query Template
, 选择EQS_FindHealthPickup
移动EQS_TestPawn到合适位置, 三个生命补给均被标记为亮蓝色, 此时无视阻挡, 以搜索半径为准
为生成器添加限制条件: 要求视线可见
Add Test > Trace
在Visibility通道计算Pawn到Actor之间是否存在其他物体阻挡视线
-
使用默认设置
- Trace > Trace Data > Trace Channel Visibility Trace > Trace Data > Trace Shape Line -
勾选则要求阻挡
-
取消勾选则要求无阻挡
-
设置为无阻挡
- Filter > Bool Match 取消勾选 通道存在阻挡则Actor被标记为蓝色; 无阻挡被标记为绿色
为生成器添加限制条件: 寻找距离最近的生命补给
Add Test > Distance
- | ||
---|---|---|
Filter > Filter Type | Minimum | |
Filter > Float Value Min | 0 | |
Score > Scoring Factor | -1 | 距离越近, 权重越大 |
为生成器添加限制条件: 存在获取生命补给的有效路径
Add Test > Path Finding
过滤掉无法去到的生命补给
使用默认设置
- | |
---|---|
Pathfinding > Test Mode | Path Exists |
在行为树中使用EQS_FindHealthPickup
-
暂时停止当前逻辑
-
添加节点: Selector
NPC寻找生命补给, 或等待 -
添加节点: Wait
设置时长为2s -
添加序列
-
为序列添加任务: RunEQSQuery
-
设置EQS
Details > EQS > EQSRequest > Query Template
, 设置为EQS_FindHealthPickupDetails > Blackboard > Blackboard Key
, 设置为AimLocation
-
为序列添加任务: MoveTo
Details > Blackboard > Blackboard Key
, 设置为AimLocation
查看
-
在选中窗口运行
-
按下
F8
或者点击Eject
-
拖动距离NPC最近的生命补给: NPC寻找并去到此时距离最近的生命补给位置
-
点击
Pause simulation
, 将所有生命补给移动到墙后, 点击Resume play-in-editor session
序列停止, NPC循环执行Wait任务
使用C++实现Decorator
检查NPC生命值, 低于给定百分比NPC才会拾取生命补给
学习BTDecorator类
在CalculateRawConditionValue中计算条件布尔值
protected
1// calculates raw, core value of decorator's condition. Should not include calling IsInversed 2virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const;
创建C++类
- | |
---|---|
基类 | BTDecorator |
名称 | STUHealthPercentDecorator |
路径 | AI/Decorators |
属性 | Public |
添加到头文件搜索路径
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 "ShootThemUp/Public/AI/Decorators" 16});
添加构造函数
public
ShootThemUp: AI/Decorators/STUHealthPercentDecorator.h
1USTUHealthPercentDecorator();
ShootThemUp: AI/Decorators/STUHealthPercentDecorator.cpp
1USTUHealthPercentDecorator::USTUHealthPercentDecorator() 2{ 3 NodeName = "Health Percent"; 4}
添加属性: 指定生命值
protected
ShootThemUp: AI/Decorators/STUHealthPercentDecorator.h
1UPROPERTY(EditAnywhere, BlueprintReadWrite) 2float HealthPercent = 0.6f;
覆写条件
protected
ShootThemUp: AI/Decorators/STUHealthPercentDecorator.h
1virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override;
通过控制器获取当前Pawn, 通过Pawn获取健康组件
ShootThemUp: AI/Decorators/STUHealthPercentDecorator.cpp
1#include "AIController.h" 2#include "STUUtils.h" 3#include "Components/STUHealthComponent.h" 4 5bool USTUHealthPercentDecorator::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const 6{ 7 const auto Controller = OwnerComp.GetAIOwner(); 8 if (!Controller) return false; 9 10 const auto HealthComponent = STUUtils::GetSTUPlayerComponent<USTUHealthComponent>(Controller->GetPawn()); 11 if (!HealthComponent || HealthComponent->IsDead()) return false; 12 13 return HealthComponent->GetHealthPercent() <= HealthPercent; 14}
使用STUHealthPercentDecorator
BT_STUCharacter
-
为Sequence添加Decorator
-
设置STUHealthPercentDecorator
- Observer aborts Self -
查看
NPC满生命值时呆在原地 > 使之生命值不大于60% > NPC去到生命补给所在
整理行为树
-
将本节新建序列移动到原行为树左侧: 优先级最高
-
作为Selector的下级; 设置Root节点
-
将Fire服务移动到选择器
NPC寻找生命补给时仍射击敌人(是否有敌人?) -
查看时注意NPC是否满足寻找生命补给条件
恢复设置
-
可以恢复Fire服务目标: 保证当前为None
-
恢复生命补给材质