如何在场景开启Debug
按F1开启线框模式
![](https://img-blog.csdnimg.cn/fe95f76d82f3481091605af08006c42c.png)
按'打开Debug数据栏
![](https://img-blog.csdnimg.cn/eec25c6d80d840f8be465911cde0ea0f.png)
按数字键3打开EQSDEBUG
![](https://img-blog.csdnimg.cn/1a3a5b67c5764f169cab2ee5b2c8e1be.png)
开启距离场debug
![](https://img-blog.csdnimg.cn/3245483f1e424166897cface93af08de.png)
![](https://img-blog.csdnimg.cn/9108eac98d0a42dfb604b2340f453be7.png)
自定义AI任务
![](https://img-blog.csdnimg.cn/22f7f340b75a4ebe9514840810c54a7f.png)
创建BTTask_RangeAttack
.h
// Fill out your copyright notice in the Description page of Project Settings. //这是创建的AI攻击任务 #pragma once #include "CoreMinimal.h" #include "BehaviorTree/BTTaskNode.h" #include "SBTTask_RangeAttack.generated.h" /** * */ UCLASS() class ACTIONROUGELIKE_API USBTTask_RangeAttack : public UBTTaskNode { GENERATED_BODY() //是否进行攻击并有返回值 virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; protected: //子弹类型 UPROPERTY(EditAnywhere,Category="AI") TSubclassOf<AActor> ProjectileClass; };
.cpp
// Fill out your copyright notice in the Description page of Project Settings. //这是创建的AI攻击任务 #include "AI/SBTTask_RangeAttack.h" #include "AIController.h" #include "BehaviorTree/BlackboardComponent.h" #include "GameFramework/Character.h" EBTNodeResult::Type USBTTask_RangeAttack::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { AAIController* MyController = OwnerComp.GetAIOwner(); if(MyController) { ACharacter* MyPawn = Cast<ACharacter>(MyController->GetPawn()); if(MyPawn == nullptr) { return EBTNodeResult::Failed; } //获取AI的手部位置 FVector MuzzleLocation = MyPawn->GetMesh()->GetSocketLocation("Muzzle_01"); //通过TargetActor变量获取到角色的Actor AActor* TargetActor = Cast<AActor>(OwnerComp.GetBlackboardComponent()->GetValueAsObject("TargetActor")); if(TargetActor == nullptr) { return EBTNodeResult::Failed; } //计算出游戏角色与AI角色手部的距离 FVector Direction = TargetActor->GetActorLocation() - MuzzleLocation; //使距离的方向为发射子弹的方向 FRotator MuzzleRoation = Direction.Rotation(); //设置碰撞 FActorSpawnParameters SpawnParameters; SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; //传入子弹,子弹Location,子弹Roation,子弹碰撞 AActor* NewProjectlie = GetWorld()->SpawnActor<AActor>(ProjectileClass,MuzzleLocation,MuzzleRoation,SpawnParameters); //检查子弹是否成功生成了,如果成功了就返回Succeed,如果失败了就返回Failed return NewProjectlie ? EBTNodeResult::Succeeded : EBTNodeResult::Failed; } return EBTNodeResult::Failed; }
在行为树中添加![](https://img-blog.csdnimg.cn/2ae7cbeb7ff64e0c83b380a3653bbe7f.png)
在攻击这里添加子弹类型![](https://img-blog.csdnimg.cn/10bf1a375daa46459b4e28c5110f383f.png)
修改BT的.cpp文件,添加视线检测并重新编译
void USBTService_CheckAtteckRange::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) { Super::TickNode(OwnerComp, NodeMemory, DeltaSeconds); //检查AI角色到玩家操控角色的距离 //这一步是确认这个角色是否拥有BlackboardComp UBlackboardComponent* BlackboardComp = OwnerComp.GetBlackboardComponent(); if(ensure(BlackboardComp)) { //通过TargetActor变量获取到角色的Actor AActor* TargetActor = Cast<AActor>(BlackboardComp->GetValueAsObject("TargetActor")); if(TargetActor) { //获取到角色Actor后从OwnerComp获得AI控制器 AAIController* MyController = OwnerComp.GetAIOwner(); if(ensure(MyController)) { //从AI控制器获取到AI的Pawn APawn* AIPawn = MyController->GetPawn(); if(ensure(AIPawn)) { //计算角色的位置和AI的位置 float DistanceTo = FVector::Distance(TargetActor->GetActorLocation() , AIPawn->GetActorLocation()); //当距离小于2000时判断为ture bool bWithinRange = DistanceTo < 2000.0f; //判断是否能看见角色,默认为看不见 bool bHasLOS = false; if(bWithinRange) { bHasLOS = MyController->LineOfSightTo(TargetActor); } //返回给黑板 BlackboardComp->SetValueAsBool(AttackRangeKey.SelectedKeyName, (bWithinRange && bHasLOS)); } } } } }
EQS
https://docs.unrealengine.com/5.0/en-US/environment-query-system-quick-start-in-unreal-engine/
UE5的EQS需要在插件中开启
创建随机移动的环境任务
![](https://img-blog.csdnimg.cn/518af831c22a4fdeafa517aa770fb12e.png)
添加Donut和Distance
![](https://img-blog.csdnimg.cn/732e454e43744d909a92f5daf3c84134.png)
将EQS添加到行为树![](https://img-blog.csdnimg.cn/5dd22eaeec3946ddaa16ef7516ac079b.png)
发现AI没有移动,进入EQS修改Filter Type![](https://img-blog.csdnimg.cn/66256f9616bf46a38e9a1479ae3bdef7.png)
发现AI只会选择最优路线,进入行为树修改为25%的容错率![](https://img-blog.csdnimg.cn/0b47d6dce10e439a8af0f0ab1a8d105a.png)