注意事项
- 绑定黑板不要在构造函数中写
- 建议在OnPossess函数绑定
定义行为树
UPROPERTY(EditAnywhere,BlueprintReadWrite, Category = "AI")
UBehaviorTree* BehaviorTreeAsset; // 关联编辑器中的行为树资源
绑定黑板
void AMyEnemyAIControllerBase::OnPossess(APawn* InPawn)
{
Super::OnPossess(InPawn);
BindBlackboardValue();
if (const auto Enemy = Cast<AMyEnemyBase>(InPawn))
{
Enemy->GetCharacterMovement()->bOrientRotationToMovement = true;
SetEnemyOutlet(Enemy->TryGetOutlet());
}
//运行行为树
if (BehaviorTreeAsset)
{
RunBehaviorTree(BehaviorTreeAsset);
}
}
void AMyEnemyAIControllerBase::BindBlackboardValue()
{
if (BehaviorTreeAsset)
{
UBlackboardComponent* MyBlackboard = nullptr;
UseBlackboard(BehaviorTreeAsset->BlackboardAsset, MyBlackboard);
}
}
void AMyEnemyAIControllerBase::SetEnemyOutlet(AMyOutletBase* OutletBase) const
{
if (OutletBase && BehaviorTreeAsset && Blackboard)
{
Blackboard->SetValueAsObject(TEXT("Outlet"), OutletBase);
UE_LOG(LogTemp, Log, TEXT("设置出怪口成功(黑板)"))
}else
{
UE_LOG(LogTemp, Error, TEXT("设置出怪口失败"));
}
}
完整的代码
AMyEnemyAIControllerBase.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Actor/Outlet/MyOutletBase.h"
#include "Runtime/AIModule/Classes/AIController.h"
#include "MyEnemyAIControllerBase.generated.h"
/**
* 怪物的AI控制器,不能直接使用
*/
UCLASS(ABstract)
class DEMO2_API AMyEnemyAIControllerBase : public AAIController
{
GENERATED_BODY()
public:
AMyEnemyAIControllerBase();
/// 控制胖时调用
virtual void OnPossess(APawn* InPawn) override;
UPROPERTY(EditAnywhere,BlueprintReadWrite, Category = "AI")
UBehaviorTree* BehaviorTreeAsset; // 关联编辑器中的行为树资源
protected:
virtual void BeginPlay() override;
UFUNCTION()
void SetEnemyOutlet(AMyOutletBase* OutletBase) const;
UFUNCTION()
void BindBlackboardValue();
public:
virtual void Tick(float DeltaTime) override;
};
AMyEnemyAIControllerBase.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "AI/MyEnemyAIControllerBase.h"
#include "BehaviorTree/BehaviorTree.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Navigation/PathFollowingComponent.h"
#include "Tool/MyCoreTool.h"
#include "Tool/MyLogTool.h"
AMyEnemyAIControllerBase::AMyEnemyAIControllerBase(): BehaviorTreeAsset(nullptr)
{
PrimaryActorTick.bCanEverTick = false;
}
/// 控制胖时调用,可以设置初始目标和行为树
void AMyEnemyAIControllerBase::OnPossess(APawn* InPawn)
{
Super::OnPossess(InPawn);
BindBlackboardValue();
if (const auto Enemy = Cast<AMyEnemyBase>(InPawn))
{
Enemy->GetCharacterMovement()->bOrientRotationToMovement = true;
SetEnemyOutlet(Enemy->TryGetOutlet());
}
//运行行为树
if (BehaviorTreeAsset)
{
RunBehaviorTree(BehaviorTreeAsset);
}
}
void AMyEnemyAIControllerBase::BeginPlay()
{
Super::BeginPlay();
}
void AMyEnemyAIControllerBase::SetEnemyOutlet(AMyOutletBase* OutletBase) const
{
if (OutletBase && BehaviorTreeAsset && Blackboard)
{
Blackboard->SetValueAsObject(TEXT("Outlet"), OutletBase);
UE_LOG(LogTemp, Log, TEXT("设置出怪口成功(黑板)"))
}else
{
UE_LOG(LogTemp, Error, TEXT("设置出怪口失败"));
}
}
void AMyEnemyAIControllerBase::BindBlackboardValue()
{
if (BehaviorTreeAsset)
{
UBlackboardComponent* MyBlackboard = nullptr;
UseBlackboard(BehaviorTreeAsset->BlackboardAsset, MyBlackboard);
}
}
void AMyEnemyAIControllerBase::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}