인공지능 - 행동트리 모델의 이해
Unreal 이론2024. 11. 10. 15:32
[이득우의 언리얼 프로그래밍 Part2 수업의 정리]
행동 트리(Behavior Tree)의 역사
- 2004년 개발사 번지의 헤일로2에서 인공지능을 설계하는데 사용됨
- 2005년 GDC에서 발표 : "Handling Complexity in the Halo 2 AI"
- 우선순위와 트리구조를 사용해 인공지능을 설계하는 기법
- 단순한 행동에서 복잡한 행동으로 이어지도록 설계
- 게임산업에서 개량해 널리 사용하고 있음
행동 트리 모델의 장점
- FSM이 가지고 있던 문제를 해결하는 새로운 게임 인공지능 모델의 수립
- 행동 트리 모델의 장점
- 모듈화 잘 되어있어 확장 자유로움
- 트리를 기반으로 계층화 잘 되어있어, 복잡한 인공지능 모델을 쉽게 설계할 수 있음
- 다이어그램으로 인공지능 모델을 효과적으로 표현할 수 있음
- 제공되는 여러 편리한 부가 기능을 활용해 다양한 상황에 대해 손쉽게 제어 가능
행동 트리 모델의 구성 요소
- 트리에서 항상 왼쪽에 있는 노드에 우선 순위 부여
- 시작 상태에서 설정할 필요 없이 왼쪽에서부터 깊이 우선 탐색(DFS)을 시작한다

행동 트리 모델의 구성 요소
- 행동을 중심으로 설계
- 단, 부모 노드에서 다수의 행동을 컨트롤. 이를 컴포짓(Composite)이라 함
- 셀렉터 (여러 행동 중 하나의 행동을 지정)
- 시퀀스 (여러 행동을 모두 수행)
- 패러렐 (여러 행동을 함께 수행)
- ex) 밥먹기, 영화보기 두 행동이 있다면
- 셀렉터: 밥과 영화 중 하나를 선택
- 시퀀스: 밥을 먹은 후 영화를 봄
- 패러렐: 밥을 먹으며 영화를 봄
- 행동에 대한 다양한 결과
- 성공 (Succeeded): 행동의 성공
- 실패 (Failed): 행동의 실패
- 중지 (Aborted): 외부 요인으로 인한 행동의 실패
- 진행 중 (InProgress): 행동 결과를 홀딩
- 컴포짓 노드마다 다른 행동 결과 처리
- 셀렉터: 성공한 노드가 나오면 종료 (밥이 안나오면 대신 영화 시청)
- 시퀀스: 실패한 노드가 나올때까지 진행 (밥을 안먹었다면 영화도 안봄)
- 컴포짓 노드에 부착하는 다양한 추가 기능
- 데코레이터(Decorator): 컴포짓 노드가 실행되는 조건 지정, 만족할때만 노드 실행
- 서비스(Service): 컴포짓 노드가 활성화될 때 주기적으로 실행하는 부가 명령
- 관찰자 중단(Abort): 데코레이터 조건에 부합되면 컴포짓 내 활동을 모두 중단
행동 트리 모델의 예시
- 퇴근하고 집에 가는 행동 트리 모델의 설정
- 지하철 역까지 이동 -> 지하철 탑승 -> 버스 환승 -> 문앞 도착
- 시퀀스 컴포짓을 사용해 이들을 묶는다.

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

컴포짓의 데코레이터 설정
- 컴포짓에 조건을 걸어 선택의 폭 넓힐 수 있도록 확장
- 우선 순위가 높은 컴포짓을 왼쪽에 배치, 데코레이터 설정

컴포짓에 관찰자 중단(Abort) 설정
- 비상상황에 대한 처리. ex) 친구로부터 함께 놀자는 연락 왔다.
- 트리 맨 왼쪽에 친구에게 간다는 컴포짓 추가
- 집에 가는 모든 컴포짓에 친구와 약속이라는 Abort 추가
- 친구에게 연락이 오면 집에 가던 모든 행동 중단 후 Root에서 다시 판단
행동 트리 모델의 구현 예시
- 전형적인 RPG 게임 NPC에 대한 행동 트리 모델 예시
- 쉬기(IDLE)와 정찰(PATROL)에 상태에 대한 행동 트리

- 전형적인 RPG 게임 플레이어에 대한 행동 트리 모델 예시
- 추가적으로 추격(CHASE)과 공격(ATTACK) 상태에 대한 행동 트리

그렇다면 실제 적용은 어떻게 하는가?

- 월드에 배치된 캐릭터, SpawnActor 함수를 사용해 스폰시킨 캐릭터 둘 중 어느쪽에 AI를 적용할지 선택하는 Auto Possess AI 옵션. 둘다 적용하도록 선택
- NPC 액터에 빙의할 AI 컨트롤러 클래스 선택하는 옵션 - 행동 트리 모델 적용한 클래스 새로 생성
// ABCharacterNonPlayer.cpp
#include "AI/ABAIController.h"
AABCharacterNonPlayer::AABCharacterNonPlayer()
{
GetMesh()->SetHiddenInGame(true);
AIControllerClass = AABAIController::StaticClass();
AutoPossessAI = EAutoPossessAI::PlacedInWorldOrSpawned;
}
- NPC 생성자 코드에 AIControllerClass 할당

- Blackboard: 인공지능 모델에서 의사결정을 하기 위한 기본 데이터 제공하는 데이터 저장소
// ABAIController.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "AIController.h"
#include "ABAIController.generated.h"
/**
*
*/
UCLASS()
class ARENABATTLE_API AABAIController : public AAIController
{
GENERATED_BODY()
public:
AABAIController();
void RunAI();
void StopAI();
protected:
// 어떤 컨트롤러가 폰에 빙의해서 조종할때 발생되는 이벤트 함수
virtual void OnPossess(APawn* InPawn) override;
private:
UPROPERTY()
TObjectPtr<class UBlackboardData> BBAsset;
UPROPERTY()
TObjectPtr<class UBehaviorTree> BTAsset;
};
// ABAIController.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "AI/ABAIController.h"
#include "BehaviorTree/BehaviorTree.h"
#include "BehaviorTree/BlackboardData.h"
#include "BehaviorTree/BlackboardComponent.h"
AABAIController::AABAIController()
{
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;
}
}
void AABAIController::RunAI()
{
UBlackboardComponent* BlackboardPtr = Blackboard.Get();
if (UseBlackboard(BBAsset, BlackboardPtr)) {
bool RunResult = RunBehaviorTree(BTAsset);
ensure(RunResult);
}
}
void AABAIController::StopAI()
{
UBehaviorTreeComponent* BTComponent = Cast<UBehaviorTreeComponent>(BrainComponent);
if (BTComponent) {
BTComponent->StopTree();
}
}
void AABAIController::OnPossess(APawn* InPawn)
{
Super::OnPossess(InPawn);
RunAI();
}
- 이후 ABAIController에서 Blackboard, BehaviorTree 에셋을 가져오고, 간단히 동작+정지 함수 구현
'Unreal 이론' 카테고리의 다른 글
| 헤드업디스플레이의 구현 (0) | 2024.11.14 |
|---|---|
| 인공지능 - 행동트리 모델의 구현 (0) | 2024.11.11 |
| 게임데이터 관리 (0) | 2024.11.06 |
| 무한 맵의 제작 (0) | 2024.10.31 |
| 아이템 시스템 (1) | 2024.10.30 |
댓글()







