Unreal 개발 본 캠프 51일차

HappyCircle·2026년 2월 10일

Unreal 개발

목록 보기
68/163

📘 TIL – Unreal Engine 몬스터 AI 시스템 설계: MoveTo + Warehouse 목표 전달 구조 설계


1. 설계 원칙 및 전제 조건

몬스터 AI가 특정 목표물(창고)을 향해 이동하는 구조를 설계할 때, 가장 중요한 것은 책임의 분리.

  • 전제: 몬스터는 플레이어를 추적하지 않고, 최종 목표인 Warehouse Actor를 향해 이동.
  • 이동 로직: BehaviorTreeMoveTo 노드를 사용.
  • 데이터 흐름: MoveTo는 단순히 이동만 담당하며, 이동 목표는 실행 전 이미 Blackboard에 세팅되어 있어야함.
  • 원칙: 목표를 찾는 복잡한 로직을 BT 내부에 두지 않고, 외부(Spawner)에서 주입하는 방식을 채택.

2. 전체 흐름 구조 (Flow)

  1. Level: Warehouse Actor를 월드에 배치합니다.
  2. Spawner: 에디터에서 지정된 DefaultWarehouseActor를 스폰된 몬스터에게 전달
  3. Monster: 주입받은 목표 정보를 보관
  4. AIController: OnPossess 시점에 Monster의 목표 정보를 Blackboard 키값으로 기록
  5. Behavior Tree: Blackboard에 저장된 WarehouseActor 키를 바탕으로 MoveTo를 실행

3. Spawner: 목표 Actor 주입

몬스터가 스폰되는 즉시 목표 지점을 알 수 있도록 데이터를 주입

// Spawner.h
UPROPERTY(EditAnywhere, Category = "Warehouse")
AActor* DefaultWarehouseActor = nullptr;

// Spawner.cpp
APotatoMonster* Monster = GetWorld()->SpawnActor<APotatoMonster>(...);

if (Monster && DefaultWarehouseActor)
{
    // 스폰 직후 몬스터 멤버 변수에 목표 주입
    Monster->WarehouseActor = DefaultWarehouseActor;
}

4. AIController: Blackboard 데이터 전달

컨트롤러는 몬스터를 조종(Possess)하기 시작할 때, 몬스터가 가진 정보를 Blackboard로 복사

C++
// MonsterAIController.cpp
void AMonsterAIController::OnPossess(APawn* InPawn)
{
    Super::OnPossess(InPawn);

    AMonster* Monster = Cast<AMonster>(InPawn);
    if (Monster && BlackboardComp)
    {
        if (Monster->WarehouseActor)
        {
            // Blackboard 키 세팅
            BlackboardComp->SetValueAsObject(FName("WarehouseActor"), Monster->WarehouseActor);
        }
        else
        {
            // 목표가 없을 경우 클리어 (MoveTo 실행 방지)
            BlackboardComp->ClearValue(FName("WarehouseActor"));
        }
    }
}

5. Behavior Tree & Blackboard 설정

Blackboard: WarehouseActor라는 이름의 Object 타입 키를 생성하고, Base Class를 Actor로 설정

Behavior Tree: MoveTo 노드의 Blackboard Key를 WarehouseActor로 지정

Target이 없으면(Null) MoveTo 노드가 실행되지 않으므로 안정성이 확보

6. 구조적 특징 및 확장 가능성

🔹 명확한 역할 분담
Spawner: "누가 어디로 가야 하는가"를 결정 (전략적 주입)

AIController: "주어진 정보를 지능 시스템에 전달" (중계)

Behavior Tree: "주어진 정보를 바탕으로 행동" (실행)

🔹 확장 시나리오
GameState 도입: Spawner가 일일이 주입하지 않고, GameState에 캐싱된 Warehouse를 AI가 가져오는 방식으로 변경 가능

게임 종료 처리: Warehouse 파괴 시 관련 이벤트를 발생시켜 모든 AI의 로직을 즉시 중단(Blackboard Key Clear)

7. 핵심 요약

사전 주입: 목표는 런타임 검색이 아닌 스폰 시점의 주입으로 확정한다.

단순화: AIController는 검색 로직 없이 Blackboard 전달자 역할만 수행한다.

안정성: 유효한 목표가 있을 때만 MoveTo가 작동하도록 설계하여 런타임 에러를 방지한다.


📘 TIL – Unreal Engine 몬스터 AI 시스템 설계: Wave / DataTable / Spawner 설계 (데이터 중심 설계)


1. 시스템 설계 목표

  • 데이터 기반 제어: 웨이브 구성, 몬스터 스탯, 특수 기믹을 코드 수정 없이 DataTable만으로 조절 가능하게 설계합니다.
  • 유연한 확장성: 새로운 몬스터 타입이나 스킬이 추가되어도 기존 로직을 건드리지 않는 구조를 지향합니다.
  • 성능 최적화: GetAllActorsOfClass 같은 무거운 월드 탐색을 제거하고 직접 참조(Reference)를 활용해 성능 안정성을 확보합니다.

2. 전체 구조 개요

시스템은 "무엇을, 언제, 어떻게"라는 질문에 따라 데이터를 계층화합니다.

  • 테이블: "무엇을 / 언제 / 얼마나"를 정의
  • Spawner: "어떤 BP(Blueprint)를 스폰할지" 결정
  • Monster: "전달받은 데이터를 적용"하여 행동

3. DataTable 역할 분리 및 상세 설계

① WaveMetaTable (웨이브 템포)

웨이브 전체의 리듬을 관리합니다. (1 웨이브 = 1 행)

  • Round, WaveId, PreDelay, SpawnInterval

② WaveSpawnTable (웨이브 구성)

특정 웨이브에 등장할 몬스터들을 정의합니다. (1 웨이브 = 다수 행)

  • WaveId, Rank (Normal/Elite/Boss), Type (EMonsterType), Count, Delay

③ TypePresetTable (몬스터 종류별 성향)

몬스터의 외형적 종류에 따른 기본 스탯을 정의합니다.

  • BaseHP, BaseAttackDamage, MoveSpeedMultiplier, ProjectileClass, OverrideBehaviorTree

④ RankPresetTable (등급별 보정)

몬스터의 등급(Normal, Elite, Boss)에 따른 스탯 배율을 정의합니다.

  • HpMultiplierMin/Max, StructureDamageMultiplier, SpecialCooldownMultiplier

⑤ SpecialSkillPresetTable (특수 기믹 정의) - 필드 정의 논의 필요(추후 구현 관련 부분)

몬스터가 가질 수 있는 특수 로직의 단일 진실 소스(Single Source of Truth)입니다.

  • SkillLogic (Split/Charge/AoE/Poison 등)
  • Trigger (OnCooldown/OnDeath/OnNearTarget)
  • TelegraphTime, Radius, DamageMultiplier, VFX

4. Spawner 설계 핵심

Spawner는 에디터 디테일 패널에서 필요한 모든 에셋을 참조하며, 런타임에 이들을 조합합니다.

🔹 주요 멤버 변수

  • 목표 참조: DefaultWarehouseActor (직접 지정)
  • 데이터 참조: 각 Preset DataTable 에셋들
  • 클래스 매핑: TMap<EMonsterType, TSubclassOf<APotatoMonster>> MonsterClassByType

🔹 MonsterClassByType 매핑 예시

테이블에 복잡한 BP 경로를 넣는 대신, 열거형(Enum)을 키값으로 클래스를 매핑합니다.
| Key (Type) | Value (Blueprint Class) |
| :--- | :--- |
| Slime | BP_Monster_Slime |
| Mimic | BP_Monster_Mimic |
| Skeleton | BP_Monster_Skeleton |
| Mushroom | BP_Monster_MushroomAngry |

📌 핵심: 타입이 늘어나면 TMap에 한 줄 추가하고 테이블에 해당 타입을 적기만 하면 즉시 스폰이 가능해집니다.


5. 시스템의 구조적 장점

  1. 안정적인 스폰: 테이블에 오타가 있거나 클래스 경로가 바뀌어도 C++ TMap에서 관리하므로 런타임 에러 대응이 쉽습니다.
  2. 기믹의 모듈화: SpecialSkillPresetTable 덕분에 특정 몬스터에게 새로운 스킬을 부여할 때 데이터 수정만으로 가능합니다.
  3. 성능 이점: 월드 내 액터를 찾기 위한 검색 과정이 없으며, 필요한 모든 데이터는 스폰 시점에 주입(Injection)됩니다.
profile
개발합시다!

0개의 댓글