본문 바로가기

공부/이득우의 언리얼 프로그래밍

[Study] Part 2 - 행동 트리 모델의 이해 (11/15)

728x90
반응형

 

 

 

  • 정리
    • 행동 트리 모델의 이해
      1. 행동 트리 모델이 가지는 장점
      2. 행동 트리 모델의 구성 요소와 설계 방법
      3. 언리얼 엔진의 행동트리를 구동시키기 위한 기본 설정
  • 행동 트리(Behavior Tree)
    • 우선순위와 트리 구조를 사용해 인공지능을 설계하는 기법
  • 행동 트리 모델의 장점
    • FSM이 가지고 있던 문제를 해결하는 새로운 게임 인공지능 모델의 수립
    • 행동 트리 모델의 장점
      • 모듈화가 잘 되어 있어 확장이 자유롭다
      • 트리를 기반으로 계층화가 잘 되어 있어, 복잡한 인공지능 모델을 쉽게 설계 가능
      • 다이어그램으로 인공지능 모델을 효과적으로 표현
      • 다양한 상황에 손쉽게 제어 가능
  • 행동 트리 모델의 구성 요소
    • 트리에서 항상 왼쪽에 있는 노드에 우선 순위를 부여
    • 시작 상태를 설정할 필요 없이 왼쪽에서부터 깊이 우선 탐색
    • 행동을 중심으로 설계
    • 단, 부모 노드에서 다수의 행동을 컨트롤 함. 이를 컴포짓(Composite)이라고 함
      • 셀렉터 (여러 행동 중 하나의 행동을 지정)
      • 시퀀스 (여러 행동을 모두 수행)
      • 패러렐 (여러 행동을 함께 수행)

 

 

행동 트리 모델의 구성 요소

 

 

  • 행동에 대한 다양한 결과
    • 성공(Succeeded) : 행동의 성공
    • 실패(Failed) : 행동의 실패
    • 중지(Aborted) : 외부 요인으로 인한 행동의 실패
    • 진행 중(InProgress) : 행동 결과를 홀딩

 

컴포짓 노드마다 다른 행동 결과 처리

 

 

  • 컴포짓 노드에 부착하는 다양한 추가 기능
  • 데코레이터(Decorator) : 컴포짓 노드가 실행되는 조건을 지정
  • 서비스(Service) : 컴포짓 노드가 활성화될 때 주기적으로 실행하는 부가 명령
  • 관찰자 중단(Abort) : 데코레이터 조건에 부합되면 컴포짓 내 활동을 모두 중단

 

 

데코레이터 / 서비스 / 관찰자 중단에 대한 예시

 

 

  • 행동 트리 모델의 예시
    • 퇴근하고 집에 가는 행동 트리 모델의 설정
      • 지하철 역까지 이동 → 지하철 탑승 → 버스 환승 → 집 도착
      • 시퀀스 컴포짓을 사용해 이를 묶는 행동 트리 모델을 만든다.

 

행동 트리 모델의 예시

 

  • 트리가 가진 깊이를 활용해 단계별로 세부적인 행동을 설계
  • 퇴근하고 집에 가기
    • 1단계 : 지하철 역까지 이동한 후, 지하철을 타고, 버스를 환승한 후, 문 앞에 도착한다.
    • 2단계 : 셀렉터 컴포짓을 사용해 지하철 역까지 걷거나 버스를 타거나 둘 중의 하나를 선택

 

행동 트리 모델의 예시

  • 행동 트리는 깊이 우선 탐색
  • 시퀀스(Sequence)는 모든 행동을 이행해야 성공
  • 셀렉터(Selector)는 둘 중 하나의 행동만 이행해도 성공
  • 관찰자 중단(Abort) 설정이 실행된다면 현재 진행 중인 컴포짓을 즉시 취소 후 루트에서부터 다시 점검한다.
    • 친구와 즉석 약속
  • 전형적인 RPG 게임 NPC에 대한 행동 트리 모델 예시
  • 쉬기(IDLE)정찰(PATROL), 추격(CHASE)공격(ATTACK) 상태에 대한 행동 트리

 

전형적인 RPG 게임 NPC에 대한 행동 트리 모델 예시

 

 

  • 실제 게임에 행동 트리 모델을 구현하기
#include "Character/ABCharacterNonPlayer.h"
#include "Engine/AssetManager.h"		// 에셋 매니저, 비동기 로드 위한
#include "AI/ABAIController.h"      // ABAIController 사용을 위한

AABCharacterNonPlayer::AABCharacterNonPlayer()
{
	GetMesh()->SetHiddenInGame(true);

	// AIControllerClass를 방금 만든 AABAIController 클래스로 변경
	AIControllerClass = AABAIController::StaticClass();

	// 배치된 NPC나 아니면 SpawnActor를 통해서 스폰시킨 NPC 두 가지 모두 다 ABAIController에 의해서 통제받도록 설정
	AutoPossessAI = EAutoPossessAI::PlacedInWorldOrSpawned;
}
  • ABCharacterNonPlayer.cpp

 

  • 에디터에서 AIController를 상속받은 ABAIController 클래스를 생성해준다.
  • 이후, ABCharacterNonPlayer 클래스로 생성된 NPCABAIController 클래스를 통해 컨트롤할 수 있도록 StaticClassAutoPossessAI를 다음과 같이 설정해준다.

 

NPC가 생성될 때 ABAIController와 NPC의 AI 속성이 변경된 것을 확인할 수 있다.

 

Artificial Intelligence>Blackboard와 Behavior Tree

 

  • Blackboard
    • 의사결정을 하기 위한 기본 데이터를 제공해주는 데이터 저장소
  • Behavior Tree
    • 행동 트리 모델

Behavior Tree

  • 앞 설명한 CompositesSelector, Sequence, Simple Parallel 등이 있다!
  • 어떤 행동을 진행할 때 이것을 감싸주는 컴포짓(Composites) 노드가 필요하다.

 

#pragma once

#include "CoreMinimal.h"
#include "AIController.h"
#include "ABAIController.generated.h"

/**
 * 
 */
UCLASS()
class ARENABATTLE_API AABAIController : public AAIController
{
	GENERATED_BODY()
	
public:
	AABAIController();

	// AI를 구동시키기 위한
	void RunAI();

	// AI를 구동을 중지시키기 위한
	void StopAI();

protected:
	// Controller에서 제공하는 OnPossess 함수 오버라이드
	// 어떤 컨트롤러가 폰에 빙의해서 조종을 할 때 발생되는 이벤트함수
	virtual void OnPossess(APawn* InPawn) override;

private:

	// BlackboardData를 저장할 변수
	UPROPERTY()
	TObjectPtr<class UBlackboardData> BBAsset;

	// BehaviorTree를 저장할 변수
	UPROPERTY()
	TObjectPtr<class UBehaviorTree> BTAsset;
};
  • ABAIController.h
#include "AI/ABAIController.h"
#include "BehaviorTree/BehaviorTree.h"				// 블랙보드 및 행동 트리에 관련된 헤더들
#include "BehaviorTree/BlackboardData.h"
#include "BehaviorTree/BlackboardComponent.h"

AABAIController::AABAIController()
{
	// 항상 해당 에셋들을 사용할 것이기 때문에 고정적으로 ConstructorHelpers를 통해서 에셋을 지정해준다.
	// Copy Reference
	static ConstructorHelpers::FObjectFinder<UBlackboardData> BBAssetRef(TEXT("/Script/AIModule.BlackboardData'/Game/ArenaBattle/AI/BB_ABCharacter.BB_ABCharacter'"));
	if (nullptr != BBAssetRef.Object)
	{
		BBAsset = BBAssetRef.Object;
	}
	static ConstructorHelpers::FObjectFinder<UBehaviorTree> BTAssetRef(TEXT("/Script/AIModule.BehaviorTree'/Game/ArenaBattle/AI/BT_ABCharacter.BT_ABCharacter'"));
	if (nullptr != BTAssetRef.Object)
	{
		BTAsset = BTAssetRef.Object;
	}
}

// AI를 구동하기 위한
void AABAIController::RunAI()
{
	// AIController에서 기본으로 멤버변수로 제공하고 있음 (Blackboard)
	UBlackboardComponent* BlackboardPtr = Blackboard.Get();
	// 블랙보드 초기화와 동시에 유효한지 체크
	if (UseBlackboard(BBAsset, BlackboardPtr))
	{
		// BehaviorTree 구동 및 확인
		bool RunResult = RunBehaviorTree(BTAsset);
		ensure(RunResult);
	}
}

// AI의 구동을 중지하기 위한
void AABAIController::StopAI()
{
	UBehaviorTreeComponent* BTComponent = Cast<UBehaviorTreeComponent>(BrainComponent);		// AIController 멤버 변수 (BrainComponent) = 지금 동작하고 있는 BehaviorTreeComponent
	if (BTComponent)
	{
		BTComponent->StopTree();
	}
}

// 폰에 빙의했을 때
void AABAIController::OnPossess(APawn* InPawn)
{
	Super::OnPossess(InPawn);

	RunAI();
}
  • ABAIController.cpp

 

  • AIController를 사용해 언리얼 엔진의 기본 핸동트리를 구동시키기 위한 기본 설정을 완료한다.
    • RunAI() : AI를 구동하기 위한
    • StopAI() : AI의 구동을 중지하기 위한
    • BrainComponent : AIController 멤버 변수인 BrainComponent, 지금 동작하고 있는 BehaviorTreeComponent

 

정상적으로 동작하고 있는 Behavior Tree

 

 

 

 

 

 

 

해당 포스트는 인프런의 <이득우의 언리얼 프로그래밍 Part2 -언리얼 게임 프레임웍의 이해>
강의를 수강하고 정리한 내용입니다.
 

이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해 | 이득우 - 인프런

청강문화산업대학교에서 언리얼 엔진, 게임 수학, UEFN 게임제작을 가르치고 있습니다. - 이득우의 언리얼 C++ 프로그래밍, 넥슨 코리아 공식 교육 교재 선정 2023 - 스마일게이트 언리얼 프로그래

www.inflearn.com

 

 

 

728x90