[UE5] 언리얼5 AI - Behavior Tree_BTService

AnJH·2024년 5월 28일

BehaviorTree_BTService

BTService는 정해진 빈도에 맞춰 Blackboard 값을 업데이트 한다.

Composite노드와 붙어서 사용되며 이렇게 업데이트된 값에 따라 하위 Composite노드 Decorator의 조건검사를 거치는 것이다.

  • BTService Class 생성

다음과 같이 BTService Class를 생성한다.

  • BTService_Detect.h
#include "CoreMinimal.h"
#include "BehaviorTree/BTService.h"
#include "BTService_Detect.generated.h"

UCLASS()
class THELASTSURVIVOR_API UBTService_Detect : public UBTService
{
	GENERATED_BODY()
	
public:
	UBTService_Detect();

protected:
	virtual void TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override;
};

지속적으로 틱을 발생시켜 적을 탐색하는 Service노드를 만들고자 한다. TickNode() 함수를 오버라이드하여 사용한다.

  • BTService_Detect.cpp
#include "BTService_Detect.h"
#include "MainAIController.h"
#include "PlayerCharacter.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "DrawDebugHelpers.h"

UBTService_Detect::UBTService_Detect()
{
	NodeName = TEXT("Detect");
	Interval = 1.0f;
}

void UBTService_Detect::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
{
	Super::TickNode(OwnerComp, NodeMemory, DeltaSeconds);

	APawn* ControllingPawn = OwnerComp.GetAIOwner()->GetPawn();
	if (ControllingPawn == nullptr) return;

	UWorld* World = ControllingPawn->GetWorld();
	FVector Center = ControllingPawn->GetActorLocation();
	float DetectRadius = 1200.0f;
	if (World == nullptr) return;

	TArray<FOverlapResult> OverlapResults;
	FCollisionQueryParams CollisionQueryParam(NAME_None, false, ControllingPawn);
	bool bResult = World->OverlapMultiByChannel(
		OverlapResults,
		Center,
		FQuat::Identity,
		ECollisionChannel::ECC_EngineTraceChannel2,
		FCollisionShape::MakeSphere(DetectRadius),
		CollisionQueryParam
	);

	if (bResult) {
		for (auto OverlapResult : OverlapResults) {
			APlayerCharacter* Player = Cast<APlayerCharacter>(OverlapResult.GetActor());
			if (Player && Player->GetController()->IsPlayerController()) {
				OwnerComp.GetBlackboardComponent()->SetValueAsObject(AMainAIController::TargetKey, Player);
				DrawDebugSphere(World, Center, DetectRadius, 16, FColor::Green, false, 0.2f);
				return;
			}
		}
	}
	else {
		OwnerComp.GetBlackboardComponent()->SetValueAsObject(AMainAIController::TargetKey, nullptr);
	}

	DrawDebugSphere(World, Center, DetectRadius, 16, FColor::Red, false, 0.2f);
}

먼저 생성자에선 Node의 이름과 해당 노드의 발생 간격을 설정해준다. 1초마다 Service노드가 실행될 것이다.

이후 Sphere형태의 Trace가 지정한 Pawn근처에서 주기적으로 동작되도록 하였고, 만약 Player가 검출되었다면 TargetKey값을 Player로 초기화시켰다.

  • Player가 검출되기 전

  • Player가 검출된 후

위와 같이 Blackboard의 Target값을 바꿔주는 것을 알 수 있다.

0개의 댓글