Unreal Engine5/KDT 2024

[UE5 KDT2024] 35. 비헤이비어트리, 블랙보드

유잉유잉유잉 2025. 3. 19. 00:05
728x90

▶️ 비헤이비어 

언리얼에서 지원하는 트리기반의 노드시스템

트리구조를 통해 ai를 컨트롤한다.

 

▶️루트 노드 

: 가장 최상위 노드. 시작점. 자식 노드로 하나의 노드만 가질 수 있다. 

 

▶️컴포짓 노드 : 트리 구조에서 여러 자식 노드를 가질 수 있는 노드.

- 자식 노드들의 어떤 순서와 조건으로 실행될 지 결정

- 노드에 데코레이터, 서비스를 부착할 수 있다.  

- 컴포짓 노드의 종류 :

1) 시퀀스 노드 (Sequence) : 왼쪽 -> 오른쪽 실행. 

- 자식 노드 중 하나라도 실패한다면 실행을 중단. 시퀀스도 실패 

 

2) 셀렉터 (Selector) : 왼쪽 -> 오른쪽 실행

- 자식 노드 중 하나라도 성공하면 실행을 중단. 셀렉터도 성공

 

3) 심플페러럴 : 메인테스크와 보조트리를 동시에 실행. 

- 메인 테스크의 겨로가가 전체 노드를 결정.

 

테스크노드 : 진짜 작업을 하는 노드 

데코레이터 : 조건을 확인하여 성공, 실패를 리턴.

  • 컴포짓이나 테스크노드에 부착 가능.

서비스 노드 : 컴포짓 또는 테스크 노드에 부착된다. 설정된 시간 간격으로 반복 실행된다.

 

▶️블랙보드 : 데이터를 저장하고 관리하는 에셋 (객체)

- 언리얼 비헤이비어트리 -> 실행 -> 데이터 



 


 

1. 블랙보드 생성

 

1) 블루프린트로 생성하기

(1)블루프린트 폴더에서 ai폴더 생성 

(2) 인공지능 - 블랙보드 - BD_MonsterDefault 생성

(3) 인공지능 - 비헤이비어트리 - BT_MonsterTree 생성

 

(4) BD_MonsterDefault 블랙보드에서 

  [1] 새 키 -> 오브젝트형 -> Target

  [2] Target선택 -> 키타입 열기 -> 베이스 클래스를 Actor로 지정.

▶️ ‘인스턴트 동기화’를 체크 하게되면 해당 블랙보드를 사용하는 모든 클래스들에게 이 데이터가 동기화된다.



2) BT_MonsterTree 에디터 

(1) selector 추가, sequence 추가

 

(2) 시퀀스 노드 선택 후 데코레이터 추가 - 블랙보드 선택 

 

(3) 블랙보드 선택 후 디테일창

블랙보드키는 Target으로 설정 

관찰자 노티파이는 OnValueChange

▶️ 관찰자 노티파이 : 

On Value Change : Target(블랙보드)의 값이 변할때 들어옴

On Result Change : 상태가 변경되는 경우 재평가 (키쿼리가 is Set 일때 사용되나봄?) 

 

▶️관찰자 중단 :

None : 중단하지 않음

LowerPriority : 해당 데코레이터가 붙은 노드의 우측 노드들을 중단

Self : 해당 데코레이터가 붙은 노드의 하위 노드들을 중단

Both : LowPriority + Self 

 

(4) 테스트용으로 비헤이비어 트리 만들고 사운드 넣기

 

(5) 만든걸 설정해봅시다.

 

[1] 비헤이비어 트리, 블랙보드 프로퍼티 추가

AMonsterAIControllerKDT 헤더에 비헤이비어 트리, 블랙보드 프로퍼티 추가 

UPROPERTY( EditAnywhere, BlueprintReadWrite )
class UBehaviorTree* mATITree;
UPROPERTY( EditAnywhere, BlueprintReadWrite )
class UBlackboardData* mBlackBoard;

 

cpp에 헤더 추가

#include "BehaviorTree/BehaviorTree.h"
#include "BehaviorTree/BlackboardData.h"
#include "BehaviorTree/BlackboardComponent.h"

AMonsterAIController::AMonsterAIController()
{
	...
	// 에셋 가져오기
	static ConstructorHelpers::FObjectFinder<UBehaviorTree> tree( L"/Script/AIModule.BehaviorTree'/Game/Blueprint/AI/BT_MonsterTree.BT_MonsterTree'" );
	if ( tree.Succeeded() )
		mATITree = tree.Object;

	static ConstructorHelpers::FObjectFinder<UBlackboardData> board( L"/Script/AIModule.BlackboardData'/Game/Blueprint/AI/BD_MonsterDefault.BD_MonsterDefault'" );
	if ( board.Succeeded() )
		mBlackBoard = board.Object;
}

 

[2] MonsterAIController에서 상속받은 AIController 의 

protected:
virtual void OnPossess( APawn* InPawn ) override;  // aiController가 폰에 빙의 될 때
virtual void OnUnPossess() override; // aiController가 폰에 빙의 해제될 때

 

가져와서 오버라이드 해주기 

void AMonsterAIControllerKDT::OnPossess( APawn* InPawn )
{
	Super::OnPossess( InPawn );

	if ( IsValid( mATITree ) && IsValid( mBlackBoard ) )
	{
		// UseBlackboard()에서 컴포넌트 비어있으면 만들어줌 
		UBlackboardComponent* comp = nullptr;
		if ( UseBlackboard( mBlackBoard, comp ) )
		{
			// 비헤이비어 트리를 실행시킴 
			RunBehaviorTree( mATITree );
		}
	}
}

▶️UseBlackboard() : 컨트롤러에 블랙보드 설정

 - UseBlackboard() 인자로 들어온 BlackboardComponent가 nullptr일 경우 내부에서 새로 생성한다. (참조로 만들어진 블랙보드컴포넌트를 넘겨준다)

▶️RunBehaviorTree() : 비헤이비어 트리 실행

 

void AMonsterAIController::OnUnPossess()
{
	Super::OnUnPossess();
}

 

=> 실행하면 블랙트리에서 설정한 사운드가 정상적으로 출력된다…

 

 

✔️ 활용방법 : 전투 / 비전투 상태 나눠서 게이지를 다르게 채운다던지

페이즈 보스 등으로 활용할 수 있다.








 

 

2. 새로운 테스크를 만들어보자

 

1) 블랙트리 에디터에서 새 테스크 추가 - ~_Print 저장

2) 생성된 BTTask_BlueprintBase_Print 에디터에서 변수 추가 - Message - 스트링링형 - 눈모양 눌러서 눈뜬상태로 변경

3) 함수 - Receive Execute 함수 만들어보자

▶️테스크 함수 오버라이드

abort : 해당 태스크 중지

execute : 실행했을 때 

Tick : 매 틱 

 

4) Excute에서 PrintString 추가 - 변수 Message가져와서 GetMessage 형태로 Print String의 InString과 연결

5) 비헤이비어 트리에 추가한 태스크 연결 (두개)

6) 오른쪽~_Print 선택 후 디테일창 - Message에 Not Found Target 추가 

7) 아래 ~_Print 선택 -> Message -> Found Target 추가 

 

▶️ 오른쪽 위 숫자가 실행 순서.

 

=>실행하면 오른쪽으로만 실행. 아직 입력한 메세지가 출력되진 않는다.

 

=> OnTargetFound()에서 액터 감지 후, 블랙보드에 데이터 저장을 해야한다.



728x90