文章目录
- 一、自定义任务节点
- 二、优化
- 1. 子弹发射冷却
- 2. 攻击时面朝玩家
一、自定义任务节点
- 本节需要创建自定义任务节点
BTTask
,实现小兵进入角色范围后进射击的功能。 - 对于
BTTaskNode
的子类,我们需要在代码中重写ExecuteTask
函数即可。返回值为EBTNodeResult::Failed
和EBTNodeResult::Successd
,对应行为树的节点返回失败或者成功。
//SBTTask_RangeAttack.h
UCLASS()
class FPSPROJECT_API USBTTask_RangeAttack : public UBTTaskNode
{GENERATED_BODY()
protected:virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;//用于角色发射投掷物攻击UPROPERTY(EditAnywhere, Category = "AI")TSubclassOf<AActor> ProjectileClass;
};//SBTTask_RangeAttack.cpp
EBTNodeResult::Type USBTTask_RangeAttack::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{AAIController* MyController = OwnerComp.GetAIOwner();if(ensure(MyController)){ACharacter* MyPawn = Cast<ACharacter>(MyController->GetPawn());if(MyPawn == nullptr){return EBTNodeResult::Failed;}AActor* TargetActor = Cast<AActor>(OwnerComp.GetBlackboardComponent()->GetValueAsObject("TargetActor"));if(TargetActor == nullptr){return EBTNodeResult::Failed;}FVector MuzzleLocation = MyPawn->GetMesh()->GetSocketLocation("Muzzle_01");//方向向量=目标位置-当前位置FVector Direction = TargetActor->GetActorLocation() - MuzzleLocation;FRotator MuzzleRotation = Direction.Rotation();FActorSpawnParameters params;params.Instigator = MyPawn;params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;ensure(ProjectileClass);AActor* NewProj = GetWorld()->SpawnActor<AActor>(ProjectileClass, MuzzleLocation, MuzzleRotation);return NewProj ? EBTNodeResult::Succeeded : EBTNodeResult::Failed;}return EBTNodeResult::Failed;
}
二、优化
1. 子弹发射冷却
Cooldown
节点会控制节点执行的间隔,当节点处于冷却时间时,会直接返回false
,以下节点自然都不会执行。Loop节点则会循环执行以下节点。
此时AI的逻辑:如果目标在攻击范围外,会向目标移动。进入攻击范围后,开枪向角色以0.5s为间隔时间射击三次,冷却2s。在此期间,行为树会运行后面两个节点,再重新判断是否结束冷却。
2. 攻击时面朝玩家
行为树自带了一个修改AI小兵的朝向服务BTService
:Set defalt focus
,从而不需要再使用SetActorRotation
函数
- 最终的完整图(包括之后的EQS):