๐ฎ Unreal Engine์ Behavior Tree๋ก AI ๊ตฌํํ๊ธฐ ๐ค

์๋ ํ์ธ์, ๊ฒ์ ๊ฐ๋ฐ ๊ฟ๋๋ฌด๋ค! ์ค๋์ ์ ๋ง ํฅ๋ฏธ์ง์งํ ์ฃผ์ ๋ก ์ฌ๋ฌ๋ถ๊ณผ ํจ๊ปํ ๊ฑฐ์์. ๋ฐ๋ก Unreal Engine์์ Behavior Tree๋ฅผ ์ฌ์ฉํด AI๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณผ ๊ฑฐ๋๋๋ค. ์ด๊ฑฐ ์์ ์ฉ์ด์! ๐
์ฌ๋ฌ๋ถ, ๊ฒ์์์ AI๊ฐ ์ผ๋ง๋ ์ค์ํ์ง ์์์ฃ ? ์ง์ง ๊ฒ์์ ๊ฝ์ด๋ผ๊ณ ํด๋ ๊ณผ์ธ์ด ์๋ ์ ๋์์. ํนํ ์์ฆ ๊ฐ์ ์๋์๋ AI ์๋ ๊ฒ์์ ์์์ด๋ ํ ์ ์๋์? ใ ใ ใ
๊ทธ๋ฐ๋ฐ ์ด AI, ์ด๋ป๊ฒ ๋ง๋ค์ด์ผ ํ ์ง ๊ณ ๋ฏผ๋์์ฃ ? ๊ฑฑ์ ๋ง์ธ์! Unreal Engine์ Behavior Tree๊ฐ ์ฌ๋ฌ๋ถ์ ๊ตฌ์์๊ฐ ๋ ๊ฑฐ์์. ์ด ๊ฐ๋ ฅํ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๋ฉด, ์ฌ๋ฌ๋ถ๋ ๊ธ๋ฐฉ ํ๋ก ๊ฐ๋ฐ์ ๋ชป์ง์์ AI๋ฅผ ๋ง๋ค ์ ์์ ๊ฑฐ์์. ์ง์ง์์, ๋ฏฟ์ด๋ณด์ธ์! ๐
์, ๊ทธ๋ผ ์ด์ ๋ถํฐ Behavior Tree์ ์ธ๊ณ๋ก ํจ๊ป ๋ ๋๋ณผ๊น์? ์ค๋น๋์ จ๋์? ๋ ์ธ ๊ณ ~! ๐โโ๏ธ๐จ
๐ณ Behavior Tree๋ ๋ญ์ผ? ๐ค
์, ์ฌ๋ฌ๋ถ! Behavior Tree๊ฐ ๋ญ์ง ์์ธ์? ๋ชจ๋ฅด์ ๋ ๊ด์ฐฎ์์. ์ง๊ธ๋ถํฐ ์ฐจ๊ทผ์ฐจ๊ทผ ์ค๋ช ํด๋๋ฆด๊ฒ์. ๐
Behavior Tree๋ ๋ง ๊ทธ๋๋ก 'ํ๋ ํธ๋ฆฌ'์์. AI์ ํ๋์ ๊ฒฐ์ ํ๋ ์์ฌ ๊ฒฐ์ ํธ๋ฆฌ๋ผ๊ณ ์๊ฐํ์๋ฉด ๋ผ์. ์ฝ๊ฒ ๋งํด, AI๊ฐ ์ด๋ค ์ํฉ์์ ์ด๋ป๊ฒ ํ๋ํ ์ง๋ฅผ ๊ฒฐ์ ํ๋ ์ฒด๊ณ์ ์ธ ๋ฐฉ๋ฒ์ด์์.
Behavior Tree๋ ๊ฒ์ AI ํ๋ก๊ทธ๋๋ฐ์์ ์ ๋ง ๋ง์ด ์ฌ์ฉ๋๋ ๊ธฐ๋ฒ์ด์์. ์ ๊ทธ๋ด๊น์? ๋ฐ๋ก AI์ ํ๋์ ์ฝ๊ฒ ์ค๊ณํ๊ณ ๊ด๋ฆฌํ ์ ์๊ธฐ ๋๋ฌธ์ด์ฃ !
๐ Behavior Tree์ ์ฅ์ :
- ๋ณต์กํ AI ๋ก์ง์ ์๊ฐ์ ์ผ๋ก ํํํ ์ ์์ด์.
- AI์ ํ๋์ ๋ชจ๋ํํ์ฌ ์ฌ์ฌ์ฉ์ฑ์ ๋์ผ ์ ์์ด์.
- ๋์์ด๋์ ํ๋ก๊ทธ๋๋จธ ๊ฐ์ ํ์ ์ ์ฝ๊ฒ ๋ง๋ค์ด์ค์.
- ๋ฐํ์์ AI์ ํ๋์ ๋์ ์ผ๋ก ๋ณ๊ฒฝํ ์ ์์ด์.
์~ ์ด๋ ๊ฒ ๋ณด๋๊น Behavior Tree ์ง์ง ๋๋จํ์ฃ ? ๊ทผ๋ฐ ์ด๊ฒ ์ด๋ป๊ฒ ์๊ฒผ๋์ง ๊ถ๊ธํ์์ฃ ? ์, ํ๋ฒ ๋ณผ๊น์? ๐
์ด๊ฒ ๋ฐ๋ก Behavior Tree์ ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์กฐ์์. ์ด๋์? ์๊ฐ๋ณด๋ค ๋ณต์กํด ๋ณด์ด์ง ์์ฃ ? ๐
Behavior Tree๋ ํฌ๊ฒ ์ธ ๊ฐ์ง ์์๋ก ๊ตฌ์ฑ๋ผ์:
- Root Node (๋ฃจํธ ๋ ธ๋): ํธ๋ฆฌ์ ์์์ ์ด์์. ๋ชจ๋ ์คํ์ ์ฌ๊ธฐ์ ์์ํด์.
- Composite Nodes (๋ณตํฉ ๋ ธ๋): Sequence๋ Selector ๊ฐ์ ๋ ธ๋๋ค์ด์์. ์์ ๋ ธ๋๋ค์ ์คํ ์์๋ฅผ ๊ฒฐ์ ํด์.
- Leaf Nodes (๋ฆฌํ ๋ ธ๋): ์ค์ ํ๋์ ์ํํ๋ Task ๋ ธ๋๋ค์ด์์.
์ด ๊ตฌ์กฐ๋ฅผ ์ด์ฉํ๋ฉด ๋ณต์กํ AI ํ๋๋ ์ฝ๊ฒ ์ค๊ณํ ์ ์์ด์. ์๋ฅผ ๋ค์ด, "์ ์ ๋ฐ๊ฒฌํ๋ฉด ๊ณต๊ฒฉํ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด ์์ฐฐํ๊ธฐ"์ ๊ฐ์ ํ๋์ ์ฝ๊ฒ ๋ง๋ค ์ ์์ฃ .
์ฌ๊ธฐ์ ์ ๊น! ๐๏ธ Behavior Tree๋ฅผ ์ด์ฉํ AI ๊ฐ๋ฐ, ์ด๋์ ๋ฐฐ์ธ ์ ์์๊น ๊ณ ๋ฏผ๋์๋์? ๊ทธ๋ด ๋ ์ฌ๋ฅ๋ท์ ํ์ฉํด๋ณด์ธ์! ์ฌ๋ฅ๋ท์์๋ ๊ฒ์ ๊ฐ๋ฐ ์ ๋ฌธ๊ฐ๋ค์ ๋ ธํ์ฐ๋ฅผ ์ฝ๊ฒ ๋ฐฐ์ธ ์ ์๋ต๋๋ค. Unreal Engine ์ ๋ฌธ๊ฐ๋ค์ ๊ฐ์๋ฅผ ๋ค์ผ๋ฉด, ์ฌ๋ฌ๋ถ๋ ๊ธ๋ฐฉ AI ๋ง์คํฐ๊ฐ ๋ ์ ์์ ๊ฑฐ์์! ๐
์, ์ด์ Behavior Tree๊ฐ ๋ญ์ง ๋์ถฉ ๊ฐ์ด ์ค์์ฃ ? ๊ทธ๋ผ ์ด์ Unreal Engine์์ ์ด๋ป๊ฒ ์ด๊ฑธ ์ฌ์ฉํ๋์ง ์์๋ณผ๊น์? ๋ค์ ์น์ ์์ ์์ธํ ์ค๋ช ํด๋๋ฆด๊ฒ์. ๊ธฐ๋๋์ง ์๋์? ์ ๋ ๋๋ฌด ์ ๋์! ๐
๐ ๏ธ Unreal Engine์์ Behavior Tree ์์ํ๊ธฐ ๐
์, ์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก Unreal Engine์์ Behavior Tree๋ฅผ ์ฌ์ฉํด๋ณผ ๊ฑฐ์์. ๊ธด์ฅ๋๋์? ๊ฑฑ์ ๋ง์ธ์, ์ ๊ฐ ์น์ ํ๊ฒ ์ค๋ช ํด๋๋ฆด๊ฒ์! ๐
๋จผ์ , Unreal Engine์ ์คํํ๊ณ ์ ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด์ฃผ์ธ์. 3์ธ์นญ ํ ํ๋ฆฟ์ผ๋ก ์์ํ๋ฉด ์ข์์. ์๋๊ณ ์? AI ์บ๋ฆญํฐ๋ฅผ ์ฝ๊ฒ ๋ง๋ค ์ ์๊ฑฐ๋ ์!
์, ์ด์ ์ฐจ๊ทผ์ฐจ๊ทผ ๋ฐ๋ผํด๋ณผ๊น์?
๐ง Behavior Tree ๊ตฌํ ๋จ๊ณ:
- AI Controller ์์ฑํ๊ธฐ
- Behavior Tree ์์ ๋ง๋ค๊ธฐ
- Blackboard ์ค์ ํ๊ธฐ
- Task์ Decorator ๋ง๋ค๊ธฐ
- Behavior Tree ๊ตฌ์ฑํ๊ธฐ
1. AI Controller ์์ฑํ๊ธฐ ๐ฎ
AI Controller๋ AI ์บ๋ฆญํฐ์ '๋๋' ์ญํ ์ ํด์. ์ด๊ฑธ ๋จผ์ ๋ง๋ค์ด์ผ ํด์!
Content Browser์์ ์ฐํด๋ฆญ โ New C++ Class โ AIController๋ฅผ ์ ํํ๊ณ ์ด๋ฆ์ ์ง์ด์ฃผ์ธ์. ์ ๋ 'MyAIController'๋ผ๊ณ ํ ๊ฒ์.
// MyAIController.h
#include "CoreMinimal.h"
#include "AIController.h"
#include "MyAIController.generated.h"
UCLASS()
class MYPROJECT_API AMyAIController : public AAIController
{
GENERATED_BODY()
public:
AMyAIController();
virtual void BeginPlay() override;
};
// MyAIController.cpp
#include "MyAIController.h"
AMyAIController::AMyAIController()
{
}
void AMyAIController::BeginPlay()
{
Super::BeginPlay();
// ์ฌ๊ธฐ์ Behavior Tree ์คํ ์ฝ๋๋ฅผ ์ถ๊ฐํ ๊ฑฐ์์!
}
์์ฐ! ์ด์ AI Controller๊ฐ ์๊ฒผ์ด์. ๊ทผ๋ฐ ์ด๊ฒ ๋ค๊ฐ ์๋์์. ์ด์ ์ค์ ๋ก AI์ ํ๋์ ๊ฒฐ์ ํ Behavior Tree๋ฅผ ๋ง๋ค์ด๋ณผ๊น์? ๐
2. Behavior Tree ์์ ๋ง๋ค๊ธฐ ๐ณ
Content Browser์์ ์ฐํด๋ฆญ โ Artificial Intelligence โ Behavior Tree๋ฅผ ์ ํํ์ธ์. ์ด๋ฆ์ 'MyBT'๋ผ๊ณ ์ง์ด๋ณผ๊ฒ์.
๋์์ Blackboard๋ ๋ง๋ค์ด์ฃผ์ธ์. Blackboard๋ AI๊ฐ ์ฌ์ฉํ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๊ณณ์ด์์. Content Browser์์ ์ฐํด๋ฆญ โ Artificial Intelligence โ Blackboard๋ฅผ ์ ํํ๊ณ 'MyBB'๋ผ๊ณ ์ด๋ฆ ์ง์ด์ฃผ์ธ์.
์ด์ ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์กฐ๊ฐ ๋ง๋ค์ด์ก์ด์! ๊ทผ๋ฐ ์์ง ์๋ฌด๊ฒ๋ ์๋ ๋น ๊ป๋ฐ๊ธฐ์ฃ ? ๊ฑฑ์ ๋ง์ธ์, ์ด์ ๋ถํฐ ํ๋์ฉ ์ฑ์๋๊ฐ ๊ฑฐ์์.
3. Blackboard ์ค์ ํ๊ธฐ ๐
Blackboard๋ฅผ ๋๋ธํด๋ฆญํด์ ์ด์ด๋ณด์ธ์. ์ฌ๊ธฐ์ AI๊ฐ ์ฌ์ฉํ ๋ณ์๋ค์ ์ถ๊ฐํ ๊ฑฐ์์.
- Vector ํ์ ์ 'TargetLocation' ์ถ๊ฐ (AI๊ฐ ์ด๋ํ ๋ชฉํ ์์น)
- Bool ํ์ ์ 'CanSeePlayer' ์ถ๊ฐ (ํ๋ ์ด์ด๋ฅผ ๋ณผ ์ ์๋์ง ์ฌ๋ถ)
์ด๋ ๊ฒ ํ๋ฉด AI๊ฐ ์ฌ์ฉํ ๊ธฐ๋ณธ์ ์ธ ๋ฐ์ดํฐ๊ฐ ์ค๋น๋์ด์. ๊ทผ์ฌํ์ฃ ? ๐
4. Task์ Decorator ๋ง๋ค๊ธฐ ๐ ๏ธ
์ด์ ์ง์ง ์ฌ๋ฏธ์๋ ๋ถ๋ถ์ด์์! AI์ ์ค์ ํ๋์ ์ ์ํ๋ Task์ ์กฐ๊ฑด์ ์ฒดํฌํ๋ Decorator๋ฅผ ๋ง๋ค์ด๋ณผ ๊ฑฐ์์.
๋จผ์ ๊ฐ๋จํ Task๋ถํฐ ๋ง๋ค์ด๋ณผ๊น์? 'MoveToTarget'์ด๋ผ๋ Task๋ฅผ ๋ง๋ค์ด๋ด์.
// MoveToTarget.h
#include "CoreMinimal.h"
#include "BehaviorTree/BTTaskNode.h"
#include "MoveToTarget.generated.h"
UCLASS()
class MYPROJECT_API UMoveToTarget : public UBTTaskNode
{
GENERATED_BODY()
public:
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
};
// MoveToTarget.cpp
#include "MoveToTarget.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "AIController.h"
EBTNodeResult::Type UMoveToTarget::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
AAIController* AIController = OwnerComp.GetAIOwner();
if (AIController == nullptr) return EBTNodeResult::Failed;
UBlackboardComponent* BlackboardComp = OwnerComp.GetBlackboardComponent();
if (BlackboardComp == nullptr) return EBTNodeResult::Failed;
FVector TargetLocation = BlackboardComp->GetValueAsVector("TargetLocation");
AIController->MoveToLocation(TargetLocation, 5.0f);
return EBTNodeResult::Succeeded;
}
์ฐ์~ ์ด์ AI๊ฐ ๋ชฉํ ์ง์ ์ผ๋ก ์ด๋ํ ์ ์๊ฒ ๋์ด์! ๐
๋ค์์ผ๋ก 'CanSeePlayer'๋ผ๋ Decorator๋ฅผ ๋ง๋ค์ด๋ณผ๊น์?
// CanSeePlayer.h
#include "CoreMinimal.h"
#include "BehaviorTree/BTDecorator.h"
#include "CanSeePlayer.generated.h"
UCLASS()
class MYPROJECT_API UCanSeePlayer : public UBTDecorator
{
GENERATED_BODY()
public:
virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override;
};
// CanSeePlayer.cpp
#include "CanSeePlayer.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "AIController.h"
#include "Kismet/GameplayStatics.h"
bool UCanSeePlayer::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const
{
AAIController* AIController = OwnerComp.GetAIOwner();
if (AIController == nullptr) return false;
APawn* AIPawn = AIController->GetPawn();
if (AIPawn == nullptr) return false;
APawn* PlayerPawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
if (PlayerPawn == nullptr) return false;
FVector PlayerLocation = PlayerPawn->GetActorLocation();
FVector AILocation = AIPawn->GetActorLocation();
FHitResult HitResult;
FCollisionQueryParams QueryParams;
QueryParams.AddIgnoredActor(AIPawn);
bool bHasLineOfSight = GetWorld()->LineTraceSingleByChannel(HitResult, AILocation, PlayerLocation, ECC_Visibility, QueryParams);
return bHasLineOfSight;
}
๋๋ฐ! ์ด์ AI๊ฐ ํ๋ ์ด์ด๋ฅผ ๋ณผ ์ ์๋์ง ์ฒดํฌํ ์ ์์ด์. ์ด ์ ๋๋ฉด ๊ธฐ๋ณธ์ ์ธ AI ํ๋์ ๋ง๋ค ์ค๋น๊ฐ ๋ค ๋๋ค์! ๐
5. Behavior Tree ๊ตฌ์ฑํ๊ธฐ ๐งฉ
์, ์ด์ ๋ชจ๋ ์ค๋น๊ฐ ๋๋ฌ์ด์. Behavior Tree๋ฅผ ์ด๊ณ ๋ ธ๋๋ค์ ์ถ๊ฐํด๋ณผ๊น์?
- Root ๋ ธ๋ ์ถ๊ฐ
- Selector ๋ ธ๋ ์ถ๊ฐ (Root์ ์์์ผ๋ก)
- Sequence ๋ ธ๋ ๋ ๊ฐ ์ถ๊ฐ (Selector์ ์์์ผ๋ก)
- ์ฒซ ๋ฒ์งธ Sequence์ 'CanSeePlayer' Decorator์ 'MoveToTarget' Task ์ถ๊ฐ
- ๋ ๋ฒ์งธ Sequence์ 'Patrol' Task ์ถ๊ฐ (์ด๊ฑด ์ฌ๋ฌ๋ถ์ด ์ง์ ๋ง๋ค์ด๋ณด์ธ์! ํํธ: ๋๋คํ ์์น๋ก ์ด๋ํ๋ Task์์)
์~ ์ ๋ง ๋๋จํด์! ์ด์ ๊ธฐ๋ณธ์ ์ธ AI ํ๋์ด ์์ฑ๋์ด์. ํ๋ ์ด์ด๋ฅผ ๋ณผ ์ ์์ผ๋ฉด ๋ฐ๋ผ๊ฐ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด ์์ฐฐํ๋ AI๊ฐ ๋ง๋ค์ด์ก์ด์! ๐๐๐
์ฌ๊ธฐ์ ์ ๊น! ๐๏ธ AI ๊ฐ๋ฐ์ด ์๊ฐ๋ณด๋ค ๋ณต์กํ๊ณ ์ด๋ ต๊ฒ ๋๊ปด์ง๋์? ๊ทธ๋ด ๋๋ง๋ค ์ฌ๋ฅ๋ท์ ๋ ์ฌ๋ ค๋ณด์ธ์. ์ฌ๋ฅ๋ท์์๋ ์ด๋ฐ ๋ณต์กํ ๊ฐ๋ฐ ๊ณผ์ ์ ์ฝ๊ฒ ์ค๋ช ํด์ฃผ๋ ์ ๋ฌธ๊ฐ๋ค์ ๊ฐ์๋ฅผ ๋ค์ ์ ์์ด์. ์ด๋ ค์ด ๋ถ๋ถ์ด ์๋ค๋ฉด, ์ฌ๋ฅ๋ท์ ๋์์ ๋ฐ์๋ณด๋ ๊ฒ๋ ์ข์ ๋ฐฉ๋ฒ์ด์์! ๐
์, ์ด์ ๊ธฐ๋ณธ์ ์ธ Behavior Tree ๊ตฌํ์ด ๋๋ฌ์ด์. ์ด๋์? ์๊ฐ๋ณด๋ค ์ด๋ ต์ง ์์ฃ ? ์ด์ ์ด๊ฑธ ๋ฐํ์ผ๋ก ๋ ๋ณต์กํ๊ณ ์ฌ๋ฏธ์๋ AI๋ฅผ ๋ง๋ค ์ ์์ ๊ฑฐ์์. ๋ค์ ์น์ ์์๋ ์ด AI๋ฅผ ๋ ๋ฐ์ ์์ผ๋ณผ ๊ฑฐ์์. ๊ธฐ๋๋์ง ์๋์? ์ ๋ ๋๋ฌด ์ ๋์! ๐๐๐
๐ Behavior Tree ๊ณ ๊ธ ๊ธฐ๋ฅ ํ์ฉํ๊ธฐ ๐ก
์ฌ๋ฌ๋ถ, ์ง๊ธ๊น์ง ์ ๋ง ์ ๋ฐ๋ผ์ค์ จ์ด์! ๐ ์ด์ ์ฐ๋ฆฌ๋ ๊ธฐ๋ณธ์ ์ธ Behavior Tree๋ฅผ ๋ง๋ค ์ ์๊ฒ ๋์ฃ . ํ์ง๋ง ์ฌ๊ธฐ์ ๋ฉ์ถ๋ฉด ์ ๋ผ์. ๋ ๋ฉ์ง AI๋ฅผ ๋ง๋ค์ด๋ณผ ๊ฑฐ์์. ์ค๋น๋์ จ๋์? ๐
1. ๋ณ๋ ฌ ์คํ (Parallel Execution) ๐โโ๏ธ๐โโ๏ธ
Behavior Tree์ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ ์ค ํ๋๋ ๋ฐ๋ก ๋ณ๋ ฌ ์คํ์ด์์. ์ฌ๋ฌ ์์ ์ ๋์์ ์ํํ ์ ์๋ค๋ ๊ฑฐ์ฃ !
์๋ฅผ ๋ค์ด, AI๊ฐ ์ด๋ํ๋ฉด์ ๋์์ ์ฃผ๋ณ์ ์ดํด๋ณผ ์ ์์ด์. ์ด๋ป๊ฒ ๊ตฌํํ ์ ์์๊น์?
// LookAround.h
#include "CoreMinimal.h"
#include "BehaviorTree/BTTaskNode.h"
#include "LookAround.generated.h"
UCLASS()
class MYPROJECT_API ULookAround : public UBTTaskNode
{
GENERATED_BODY()
public:
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
virtual void TickTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override;
UPROPERTY(EditAnywhere, Category = "AI")
float RotationSpeed = 60.0f;
};
// LookAround.cpp
#include "LookAround.h"
#include "AIController.h"
EBTNodeResult::Type ULookAround::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
// ํ์คํฌ ์์
return EBTNodeResult::InProgress;
}
void ULookAround::TickTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
{
AAIController* AIController = OwnerComp.GetAIOwner();
if (AIController == nullptr) return;
APawn* AIPawn = AIController->GetPawn();
if (AIPawn == nullptr) return;
// AI๋ฅผ ์ฒ์ฒํ ํ์ ์ํต๋๋ค.
FRotator NewRotation = AIPawn->GetActorRotation();
NewRotation.Yaw += RotationSpeed * DeltaSeconds;
AIPawn->SetActorRotation(NewRotation);
}
์ด์ ์ด Task๋ฅผ Parallel ๋ ธ๋ ์๋์ MoveToTarget๊ณผ ํจ๊ป ๋ฃ์ผ๋ฉด, AI๊ฐ ์ด๋ํ๋ฉด์ ๋์์ ์ฃผ๋ณ์ ๋๋ฌ๋ณผ ๊ฑฐ์์. ๋ฉ์ง์ฃ ? ๐ฎ
2. ์๋น์ค (Services) ํ์ฉํ๊ธฐ ๐ ๏ธ
์๋น์ค๋ ์ฃผ๊ธฐ์ ์ผ๋ก ์คํ๋๋ ๋ ธ๋์์. ์๋ฅผ ๋ค์ด, ํ๋ ์ด์ด์ ์์น๋ฅผ ๊ณ์ ์ ๋ฐ์ดํธํ๋ ์๋น์ค๋ฅผ ๋ง๋ค์ด๋ณผ๊น์?
// UpdatePlayerLocation.h
#include "CoreMinimal.h"
#include "BehaviorTree/BTService.h"
#include "UpdatePlayerLocation.generated.h"
UCLASS()
class MYPROJECT_API UUpdatePlayerLocation : public UBTService
{
GENERATED_BODY()
public:
UUpdatePlayerLocation();
protected:
virtual void TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override;
};
// UpdatePlayerLocation.cpp
#include "UpdatePlayerLocation.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "Kismet/GameplayStatics.h"
UUpdatePlayerLocation::UUpdatePlayerLocation()
{
NodeName = "Update Player Location";
Interval = 0.5f; // 0.5์ด๋ง๋ค ์คํ
}
void UUpdatePlayerLocation::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("PlayerLocation", PlayerPawn->GetActorLocation());
}
์ด ์๋น์ค๋ฅผ Behavior Tree์ ๋ฃจํธ ๋ ธ๋์ ์ถ๊ฐํ๋ฉด, AI๊ฐ ํญ์ ์ต์ ํ๋ ์ด์ด ์์น๋ฅผ ์ ์ ์์ด์. ์์ ๋๋ํด์ก์ฃ ? ๐ง
3. ๋ฐ์ฝ๋ ์ดํฐ (Decorators) ์ฌํ ๐ญ
์ฐ๋ฆฌ๊ฐ ์ด์ ์ ๋ง๋ CanSeePlayer ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ข ๋ ๋ฐ์ ์์ผ๋ณผ๊น์? ์ด๋ฒ์๋ ์์ผ ๊ฐ๋์ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ ๋ คํด๋ณผ๊ฒ์.
// AdvancedCanSeePlayer.h
#include "CoreMinimal.h"
#include "BehaviorTree/BTDecorator.h"
#include "AdvancedCanSeePlayer.generated.h"
UCLASS()
class MYPROJECT_API UAdvancedCanSeePlayer : public UBTDecorator
{
GENERATED_BODY()
public:
virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override;
UPROPERTY(EditAnywhere, Category = "AI")
float ViewAngle = 60.0f;
UPROPERTY(EditAnywhere, Category = "AI")
float ViewDistance = 1000.0f;
};
// AdvancedCanSeePlayer.cpp
#include "AdvancedCanSeePlayer.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "AIController.h"
#include "Kismet/GameplayStatics.h"
#include "DrawDebugHelpers.h"
bool UAdvancedCanSeePlayer::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const
{
AAIController* AIController = OwnerComp.GetAIOwner();
if (AIController == nullptr) return false;
APawn* AIPawn = AIController->GetPawn();
if (AIPawn == nullptr) return false;
APawn* PlayerPawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
if (PlayerPawn == nullptr) return false;
FVector AILocation = AIPawn->GetActorLocation();
FVector PlayerLocation = PlayerPawn->GetActorLocation();
// ๊ฑฐ๋ฆฌ ์ฒดํฌ
if (FVector::Dist(AILocation, PlayerLocation) > ViewDistance)
return false;
// ๊ฐ๋ ์ฒดํฌ
FVector AIForward = AIPawn->GetActorForwardVector();
FVector AIToPlayer = (PlayerLocation - AILocation).GetSafeNormal();
float AngleBetween = FMath ::RadiansToDegrees(FMath::Acos(FVector::DotProduct(AIForward, AIToPlayer)));
if (AngleBetween > ViewAngle / 2.0f)
return false;
// ์์ผ ์ฐจ๋จ ์ฒดํฌ
FHitResult HitResult;
FCollisionQueryParams QueryParams;
QueryParams.AddIgnoredActor(AIPawn);
bool bHasLineOfSight = !GetWorld()->LineTraceSingleByChannel(HitResult, AILocation, PlayerLocation, ECC_Visibility, QueryParams);
// ๋๋ฒ๊ทธ ์๊ฐํ (์ ํ์ฌํญ)
#if WITH_EDITOR
DrawDebugLine(GetWorld(), AILocation, PlayerLocation, bHasLineOfSight ? FColor::Green : FColor::Red, false, 0.1f);
#endif
return bHasLineOfSight;
}
์์ฐ! ์ด์ AI๋ ์ง์ง ๋์ด ๋ฌ๋ฆฐ ๊ฒ์ฒ๋ผ ํ๋ํ ๊ฑฐ์์. ์์ผ๊ฐ๊ณผ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ ๋ คํด์ ํ๋ ์ด์ด๋ฅผ ๊ฐ์งํ๋๊น์. ๐
4. ์กฐ๊ฑด๋ถ ์ค๋จ (Conditional Abort) ๐ฆ
Behavior Tree์ ๋ ๋ค๋ฅธ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ์กฐ๊ฑด๋ถ ์ค๋จ์ด์์. ์๋ฅผ ๋ค์ด, AI๊ฐ ์์ฐฐ ์ค์ ๊ฐ์๊ธฐ ํ๋ ์ด์ด๋ฅผ ๋ฐ๊ฒฌํ๋ฉด ์ฆ์ ์ถ๊ฒฉ์ผ๋ก ์ ํํ ์ ์์ฃ .
์ด๋ฅผ ์ํด ์ฐ๋ฆฌ์ Selector ๋ ธ๋์ 'Abort Self'๋ 'Abort Lower Priority' ์ต์ ์ ์ค์ ํ ์ ์์ด์. ์ด๋ ๊ฒ ํ๋ฉด ์กฐ๊ฑด์ด ๋ฐ๋์์ ๋ ํ์ฌ ์คํ ์ค์ธ ์์ ์ ์ค๋จํ๊ณ ๋ค๋ฅธ ์์ ์ผ๋ก ์ ํํ ์ ์์ฃ .
Behavior Tree ์๋ํฐ์์ Selector ๋ ธ๋๋ฅผ ์ ํํ๊ณ Details ํจ๋์์ ์ด ์ต์ ์ ์ค์ ํด๋ณด์ธ์. ๋๋ผ์ด ๋ณํ๋ฅผ ๊ฒฝํํ์ค ์ ์์ ๊ฑฐ์์! ๐ญ
5. ๋ธ๋๋ณด๋ ํ์ฉํ๊ธฐ ๐
๋ธ๋๋ณด๋๋ฅผ ๋ ํจ๊ณผ์ ์ผ๋ก ํ์ฉํด๋ณผ๊น์? AI์ ์ํ๋ฅผ ๋ํ๋ด๋ ์ด๊ฑฐํ ๋ณ์๋ฅผ ์ถ๊ฐํด๋ด์.
// AIState ์ด๊ฑฐํ ์ ์ (ํค๋ ํ์ผ์)
UENUM(BlueprintType)
enum class EAIState : uint8
{
Idle,
Patrolling,
Chasing,
Attacking
};
// ๋ธ๋๋ณด๋์ AIState ํค ์ถ๊ฐ
์ด์ AI์ ์ํ์ ๋ฐ๋ผ ๋ค๋ฅธ ํ๋์ ์ทจํ๋๋ก Behavior Tree๋ฅผ ๊ตฌ์ฑํ ์ ์์ด์. ์๋ฅผ ๋ค์ด:
- Idle ์ํ์ผ ๋๋ ์ ์๋ฆฌ์์ ์ฃผ๋ณ์ ์ดํด๋ด์.
- Patrolling ์ํ์ผ ๋๋ ์ ํด์ง ๊ฒฝ๋ก๋ฅผ ๋ฐ๋ผ ์ด๋ํด์.
- Chasing ์ํ์ผ ๋๋ ํ๋ ์ด์ด๋ฅผ ์ซ์๊ฐ์.
- Attacking ์ํ์ผ ๋๋ ๊ณต๊ฒฉ ์ ๋๋ฉ์ด์ ์ ์ฌ์ํ๊ณ ๋ฐ๋ฏธ์ง๋ฅผ ์ค์.
์ด๋ ๊ฒ ํ๋ฉด AI์ ํ๋์ด ํจ์ฌ ๋ ๋ค์ํ๊ณ ์์ฐ์ค๋ฌ์์ง ๊ฑฐ์์! ๐
๋ง๋ฌด๋ฆฌ ๐
์ฌ๋ฌ๋ถ, ์ ๋ง ๋๋จํด์! ์ด์ ์ฌ๋ฌ๋ถ์ Unreal Engine์ Behavior Tree๋ฅผ ํ์ฉํด ๋ณต์กํ๊ณ ์ง๋ฅ์ ์ธ AI๋ฅผ ๋ง๋ค ์ ์๊ฒ ๋์ด์. ์ด ๊ธฐ์ ๋ค์ ์กฐํฉํ๋ฉด ์ ๋ง ๋๋ผ์ด AI๋ฅผ ๋ง๋ค ์ ์์ ๊ฑฐ์์.
ํ์ง๋ง ๊ธฐ์ตํ์ธ์, AI ๊ฐ๋ฐ์ ๋์์๋ ํ์ต๊ณผ ์คํ์ ๊ณผ์ ์ด์์. ์ฌ๋ฌ๋ถ๋ง์ ๋ ํนํ ์์ด๋์ด๋ฅผ ์ถ๊ฐํด ๋์ฑ ํฅ๋ฏธ์ง์งํ AI๋ฅผ ๋ง๋ค์ด๋ณด์ธ์!
๊ทธ๋ฆฌ๊ณ ์์ง ๋ง์ธ์! ์ด๋ ค์ด ๋ถ๋ถ์ด ์๋ค๋ฉด ์ธ์ ๋ ์ฌ๋ฅ๋ท์ ํ์ฉํด๋ณด์ธ์. ์ ๋ฌธ๊ฐ๋ค์ ์กฐ์ธ์ ๋ค์ผ๋ฉด ๋ ๋น ๋ฅด๊ฒ ์ฑ์ฅํ ์ ์์ ๊ฑฐ์์. ์ฌ๋ฌ๋ถ์ ๊ฒ์ ๊ฐ๋ฐ ์ฌ์ ์ ์์ํฉ๋๋ค! ํ์ดํ ! ๐ช๐
๐ฎ ๋ง๋ฌด๋ฆฌ: AI์ ๋ฌดํํ ๊ฐ๋ฅ์ฑ ๐
์ฌ๋ฌ๋ถ, ์ ๋ง ๋๋จํด์! ๐๐๐ ์ด์ ์ฌ๋ฌ๋ถ์ Unreal Engine์ Behavior Tree๋ฅผ ์ฌ์ฉํด ๋ณต์กํ๊ณ ์ง๋ฅ์ ์ธ AI๋ฅผ ๋ง๋ค ์ ์๊ฒ ๋์ด์. ์ด๊ฑด ์ ๋ง ๋๋จํ ์ฑ๊ณผ์์!
์ฐ๋ฆฌ๊ฐ ํจ๊ป ๋ฐฐ์ด ๋ด์ฉ์ ๋ค์ ํ๋ฒ ์ ๋ฆฌํด๋ณผ๊น์?
- Behavior Tree์ ๊ธฐ๋ณธ ๊ตฌ์กฐ์ ์๋ ์๋ฆฌ
- AI Controller ์์ฑ ๋ฐ ์ค์
- Task, Decorator, Service ๋ ธ๋ ๊ตฌํ
- ๋ณ๋ ฌ ์คํ์ ํตํ ๋ณต์กํ ํ๋ ๊ตฌํ
- ๊ณ ๊ธ ์์ผ ๊ฐ์ง ์์คํ
- ์กฐ๊ฑด๋ถ ์ค๋จ์ ํตํ ๋์ ํ๋ ์ ํ
- ๋ธ๋๋ณด๋๋ฅผ ํ์ฉํ ์ํ ๊ด๋ฆฌ
์ด ๋ชจ๋ ๊ฒ๋ค์ ์กฐํฉํ๋ฉด, ์ฌ๋ฌ๋ถ์ ์ด์ ๊ฑฐ์ ๋ชจ๋ ์ข ๋ฅ์ AI๋ฅผ ๋ง๋ค ์ ์์ด์. ์ AI, NPC, ๋๋ฌผ AI, ์ฌ์ง์ด ๋ณต์กํ ์ ๋ต ๊ฒ์์ AI๊น์ง๋ ๊ฐ๋ฅํด์!
ํ์ง๋ง ๊ธฐ์ตํ์ธ์. ์ด๊ฑด ์์์ ๋ถ๊ณผํด์. AI ๊ฐ๋ฐ์ ์ธ๊ณ๋ ๋ฌด๊ถ๋ฌด์งํด์. ์ฌ๋ฌ๋ถ์ด ์์ํ ์ ์๋ ๋ชจ๋ ๊ฒ์ AI๋ก ๊ตฌํํ ์ ์์ด์. ์ด๋ค ์์ด๋์ด๊ฐ ๋ ์ค๋ฅด๋์? ๐ค
๋ช ๊ฐ์ง ์ฌ๋ฏธ์๋ ์์ด๋์ด๋ฅผ ์ ์ํด๋ณผ๊ฒ์:
- ๊ฐ์ ์์คํ ์ ์ถ๊ฐํด AI์ ๊ธฐ๋ถ์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ํ๋ํ๋๋ก ๋ง๋ค์ด๋ณด๋ ๊ฑด ์ด๋จ๊น์?
- ํ์ต ์์คํ ์ ๊ตฌํํด AI๊ฐ ํ๋ ์ด์ด์ ํ๋ ํจํด์ ํ์ตํ๊ณ ๋์ํ๋๋ก ๋ง๋ค์ด๋ณด๋ ๊ฒ๋ ์ฌ๋ฐ์ ๊ฑฐ์์.
- ์ฌ๋ฌ AI๊ฐ ํ๋ ฅํ๋ ์์คํ ์ ๋ง๋ค์ด ํ์ํฌ๋ฅผ ๊ตฌํํด๋ณด๋ ๊ฒ๋ ๋์ ํด๋ณผ ๋งํด์.
๊ฐ๋ฅ์ฑ์ ๋ฌดํํด์! ์ฌ๋ฌ๋ถ์ ์์๋ ฅ์ด ๊ณง ํ๊ณ์์. ๐
๊ทธ๋ฆฌ๊ณ ์์ง ๋ง์ธ์. AI ๊ฐ๋ฐ์ ๋์์๋ ํ์ต๊ณผ ์คํ์ ๊ณผ์ ์ด์์. ๋๋ก๋ ์ด๋ ค์ธ ์๋ ์๊ณ , ์ข์ ํ ์๋ ์์ด์. ํ์ง๋ง ๊ทธ๋ด ๋๋ง๋ค ์ฌ๋ฅ๋ท์ ๋ ์ฌ๋ ค๋ณด์ธ์. ์ ๋ฌธ๊ฐ๋ค์ ์กฐ์ธ๊ณผ ๋์์ ๋ฐ์ผ๋ฉด, ์ด๋ ค์ด ๊ณ ๋น๋ ์ฝ๊ฒ ๋๊ธธ ์ ์์ ๊ฑฐ์์.
์ฌ๋ฌ๋ถ์ ๊ฒ์ ๊ฐ๋ฐ ์ฌ์ ์ ์ง์ฌ์ผ๋ก ์์ํฉ๋๋ค. ์ฌ๋ฌ๋ถ์ด ๋ง๋ค ๋ฉ์ง ๊ฒ์๊ณผ AI๋ค์ด ์ ๋ง ๊ธฐ๋๋ผ์! ์ธ์ ๊ฐ ์ฌ๋ฌ๋ถ์ด ๋ง๋ ๊ฒ์์ ํ๋ ์ดํ๊ฒ ๋ ๋ ์ ๊ฟ๊พธ๋ฉฐ, ์ด ๊ฐ์๋ฅผ ๋ง์น๊ฒ ์ต๋๋ค.
ํ์ดํ ! ์ฌ๋ฌ๋ถ์ ํ ์ ์์ด์! ๐๐ฎ๐ช
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ