[Unreal]#19_Custom Behavior Tree Service
Unreal 개발 중 "Behavior Tree Service"에 대해 알아보겠습니다.
"Simple Shooter Game"의 AI Player 개발 내용입니다.
Behavior Tree Service
- BT_Service는 Background Task들을 실행하기 위한 노드로서, AI가 필요로 하는 정보들을 Update 합니다.
UBTService_UpdateLastKnownPlayerLocation
* UpdatePlaeyrLocation 네이밍을 UdpateLastKnownPlayerLocation이라 가정하겠습니다.
1. UBTService_UpdateLastKnownPlayerLocation
- Blackboard에서 생성한 Key 값과 관련된 서비스를 생성하기 위해 Blackboard Base의 클래스를 생성합니다.
2. UBTService_UpdateLastKnownPlayerLocation.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "BehaviorTree/Services/BTService_BlackboardBase.h"
#include "BTService_UpdatePlayerLocation.generated.h"
/**
*
*/
UCLASS()
class SIMPLESHOOTERNEW_API UBTService_UpdatePlayerLocation : public UBTService_BlackboardBase
{
GENERATED_BODY()
public:
UBTService_UpdatePlayerLocation();
protected:
// From UBTService
virtual void TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override;
};
3. UBTService.h
virtual void TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override;
- 매 Frame마다 호출되는 메서드입니다.
4. UBTService_UpdateLastKnownPlayerLocation.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "BTService_UpdatePlayerLocation.h"
#include "Kismet/GameplayStatics.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "GameFramework/Pawn.h"
UBTService_UpdatePlayerLocation::UBTService_UpdatePlayerLocation()
{
NodeName = "Update Player Location";
}
void UBTService_UpdatePlayerLocation::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
{
Super::TickNode(OwnerComp, NodeMemory, DeltaSeconds);
APawn* PlayerPawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
if(PlayerPawn == nullptr)
return;
OwnerComp.GetBlackboardComponent()->SetValueAsVector(GetSelectedBlackboardKey(), PlayerPawn->GetActorLocation());
}
- Blackboard의 "Last Know Player Location"키의 값을 매 Frame마다 업데이트합니다.
UBTService_PlayerLocationIfFound
1. UBTService_PlayerLocationIfFound.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "BehaviorTree/Services/BTService_BlackboardBase.h"
#include "BTService_PlayerLocationIfFound.generated.h"
/**
*
*/
UCLASS()
class SIMPLESHOOTERNEW_API UBTService_PlayerLocationIfFound : public UBTService_BlackboardBase
{
GENERATED_BODY()
public:
UBTService_PlayerLocationIfFound();
protected:
// From UBTService
virtual void TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override;
};
2. UBTService_PlayerLocationIfFound
// Fill out your copyright notice in the Description page of Project Settings.
#include "BTService_PlayerLocationIfFound.h"
#include "Kismet/GameplayStatics.h"
#include "GameFramework/Pawn.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "AIController.h"
UBTService_PlayerLocationIfFound::UBTService_PlayerLocationIfFound()
{
NodeName = "Update Player Location If Seen";
}
void UBTService_PlayerLocationIfFound::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
{
Super::TickNode(OwnerComp, NodeMemory, DeltaSeconds);
APawn* PlayerPawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
if(PlayerPawn == nullptr)
return;
if(OwnerComp.GetAIOwner() == nullptr)
return;
// 1. AI Controller의 Line Of Signt(시야)에 Player가 감지되는지 검사합니다.
if(OwnerComp.GetAIOwner()->LineOfSightTo(PlayerPawn))
{
// 2. 감지 되었다면, Player Location 키 값을 설정합니다.
OwnerComp.GetBlackboardComponent()->SetValueAsVector(GetSelectedBlackboardKey(), PlayerPawn->GetActorLocation());
}
else
{
// 3. 감지 되지 않았다면, Player Location 키 값을 Clear합니다.
OwnerComp.GetBlackboardComponent()->ClearValue(GetSelectedBlackboardKey());
}
}
AShooterAIController
1. AShooterAIController.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "ShooterAIController.h"
#include "Kismet/GameplayStatics.h"
#include "BehaviorTree/BlackboardComponent.h"
void AShooterAIController::BeginPlay()
{
Super::BeginPlay();
PlayerPawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
if(AIBehaviorTree != nullptr)
{
RunBehaviorTree(AIBehaviorTree);
// Bloackboard Component Setting Here
GetBlackboardComponent()->SetValueAsVector(TEXT("Player Location"), PlayerPawn->GetActorLocation());
GetBlackboardComponent()->SetValueAsVector(TEXT("Start Location"), GetPawn()->GetActorLocation());
}
}
void AShooterAIController::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
/*
if(PlayerPawn != nullptr)
{
if(LineOfSightTo(PlayerPawn))
{
GetBlackboardComponent()->SetValueAsVector(TEXT("Player Location"), PlayerPawn->GetActorLocation());
GetBlackboardComponent()->SetValueAsVector(TEXT("Last Known Player Location"), PlayerPawn->GetActorLocation());
}else
{
GetBlackboardComponent()->ClearValue(TEXT("Player Location"));
}
}
*/
}
- Tick 메서드에 작성했던 "LineOfSightTo" 관련 코드들을 모두 지워줍니다.
Behavior Tree
1. Service 추가 화면
- Set Default Focus(제공 서비스): Focal Point의 기준이 될 위치 혹은 객체를 설정합니다.
- Update Player Location If Seen: Line Of Sight에 Player가 인지되었다면, Player Location 값을 설정합니다.
- Update (Last Known) Player Location : Last Known Player Location 키 값을 설정합니다.
테스트 화면
'게임개발 > Unreal C++' 카테고리의 다른 글
[Unreal]#21_Custom Delegate (0) | 2022.11.02 |
---|---|
[Unreal]#20_Log (0) | 2022.11.02 |
[Unreal]#18_Custom Behavior Tree Task (0) | 2022.10.05 |
[Unreal]#17_Behavior Tree (1) | 2022.10.04 |
[Unreal]#16_Behavior Tree Setting (0) | 2022.10.02 |