BTService는 정해진 빈도에 맞춰 Blackboard 값을 업데이트 한다.
Composite노드와 붙어서 사용되며 이렇게 업데이트된 값에 따라 하위 Composite노드 Decorator의 조건검사를 거치는 것이다.

다음과 같이 BTService Class를 생성한다.
#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() 함수를 오버라이드하여 사용한다.
#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값을 바꿔주는 것을 알 수 있다.