728x90
반응형
- 정리
- 행동 트리 모델의 이해
- 행동 트리 모델이 가지는 장점
- 행동 트리 모델의 구성 요소와 설계 방법
- 언리얼 엔진의 행동트리를 구동시키기 위한 기본 설정
- 행동 트리 모델의 이해
- 행동 트리(Behavior Tree)
- 우선순위와 트리 구조를 사용해 인공지능을 설계하는 기법
- 행동 트리 모델의 장점
- FSM이 가지고 있던 문제를 해결하는 새로운 게임 인공지능 모델의 수립
- 행동 트리 모델의 장점
- 모듈화가 잘 되어 있어 확장이 자유롭다
- 트리를 기반으로 계층화가 잘 되어 있어, 복잡한 인공지능 모델을 쉽게 설계 가능
- 다이어그램으로 인공지능 모델을 효과적으로 표현
- 다양한 상황에 손쉽게 제어 가능
- 행동 트리 모델의 구성 요소
- 트리에서 항상 왼쪽에 있는 노드에 우선 순위를 부여
- 시작 상태를 설정할 필요 없이 왼쪽에서부터 깊이 우선 탐색
- 행동을 중심으로 설계
- 단, 부모 노드에서 다수의 행동을 컨트롤 함. 이를 컴포짓(Composite)이라고 함
- 셀렉터 (여러 행동 중 하나의 행동을 지정)
- 시퀀스 (여러 행동을 모두 수행)
- 패러렐 (여러 행동을 함께 수행)
- 행동에 대한 다양한 결과
- 성공(Succeeded) : 행동의 성공
- 실패(Failed) : 행동의 실패
- 중지(Aborted) : 외부 요인으로 인한 행동의 실패
- 진행 중(InProgress) : 행동 결과를 홀딩
- 컴포짓 노드에 부착하는 다양한 추가 기능
- 데코레이터(Decorator) : 컴포짓 노드가 실행되는 조건을 지정
- 서비스(Service) : 컴포짓 노드가 활성화될 때 주기적으로 실행하는 부가 명령
- 관찰자 중단(Abort) : 데코레이터 조건에 부합되면 컴포짓 내 활동을 모두 중단
- 행동 트리 모델의 예시
- 퇴근하고 집에 가는 행동 트리 모델의 설정
- 지하철 역까지 이동 → 지하철 탑승 → 버스 환승 → 집 도착
- 시퀀스 컴포짓을 사용해 이를 묶는 행동 트리 모델을 만든다.
- 퇴근하고 집에 가는 행동 트리 모델의 설정
- 트리가 가진 깊이를 활용해 단계별로 세부적인 행동을 설계
- 퇴근하고 집에 가기
- 1단계 : 지하철 역까지 이동한 후, 지하철을 타고, 버스를 환승한 후, 문 앞에 도착한다.
- 2단계 : 셀렉터 컴포짓을 사용해 지하철 역까지 걷거나 버스를 타거나 둘 중의 하나를 선택
- 행동 트리는 깊이 우선 탐색
- 시퀀스(Sequence)는 모든 행동을 이행해야 성공
- 셀렉터(Selector)는 둘 중 하나의 행동만 이행해도 성공
- 관찰자 중단(Abort) 설정이 실행된다면 현재 진행 중인 컴포짓을 즉시 취소 후 루트에서부터 다시 점검한다.
- 친구와 즉석 약속
- 전형적인 RPG 게임 NPC에 대한 행동 트리 모델 예시
- 쉬기(IDLE)와 정찰(PATROL), 추격(CHASE)과 공격(ATTACK) 상태에 대한 행동 트리
- 실제 게임에 행동 트리 모델을 구현하기
#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 클래스로 생성된 NPC를 ABAIController 클래스를 통해 컨트롤할 수 있도록 StaticClass와 AutoPossessAI를 다음과 같이 설정해준다.
- Blackboard
- 의사결정을 하기 위한 기본 데이터를 제공해주는 데이터 저장소
- Behavior Tree
- 행동 트리 모델
- 앞 설명한 Composites의 Selector, 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
해당 포스트는 인프런의 <이득우의 언리얼 프로그래밍 Part2 -언리얼 게임 프레임웍의 이해>
강의를 수강하고 정리한 내용입니다.
이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해 | 이득우 - 인프런
청강문화산업대학교에서 언리얼 엔진, 게임 수학, UEFN 게임제작을 가르치고 있습니다. - 이득우의 언리얼 C++ 프로그래밍, 넥슨 코리아 공식 교육 교재 선정 2023 - 스마일게이트 언리얼 프로그래
www.inflearn.com
728x90
'공부 > 이득우의 언리얼 프로그래밍' 카테고리의 다른 글
[Study] Part 2 - 헤드업디스플레이의 구현 (13/15) (0) | 2024.06.21 |
---|---|
[Study] Part 2 - 행동 트리 모델의 구현 (12/15) (0) | 2024.06.20 |
[Study] Part 2 - 게임데이터 관리 (10/15) (0) | 2024.06.18 |
[Study] Part 2 - 무한맵의 제작 (9/15) (0) | 2024.06.17 |
[Study] Part 2 - 아이템 시스템 (8/15) (0) | 2024.06.13 |