📘 TIL : Unreal Engine 몬스터 AI 설계 + 토너먼트 알고리즘 분석
🧠 오늘의 이슈
- 알고리즘 → 토너먼트는 “번호 문제”가 아니라 “이진 트리 구조”
- Unreal AI → 이동은 “경로 탐색”이 아니라 “역할 분리된 시스템 설계”
1️⃣ [Algorithm] 토너먼트 라운드 계산 문제 분석
📌 문제 요약
- N명의 참가자가 토너먼트 진행 (매 라운드 1-2, 3-4... 대진)
- 승자는 다음 라운드에서 다시 1번부터 번호 부여
- A와 B가 몇 라운드에서 만나는가?
❌ 잘못된 초기 접근
if (abs(a - b) <= 1) -> 번호 차이가 1이면 만난다?
- 반례: N=8에서 a=4, b=5인 경우 번호 차이는 1이지만 서로 다른 경기조에 속함 (라운드 3에서 만남).
- 즉, 단순 번호 차이로는 해결 불가.
✅ 정석 풀이 (이진 트리 구조)
토너먼트는 사실상 완전 이진 트리 구조이며, 매 라운드마다 번호가 갱신되는 규칙은 부모 노드로 이동하는 것과 동일합니다.
Next Number=2Current Number+1
int solution(int n, int a, int b)
{
int round = 0;
while (a != b)
{
a = (a + 1) / 2;
b = (b + 1) / 2;
round++;
}
return round;
}
2️⃣ [Unreal] MoveTo + Warehouse 목표 전달 구조 설계
📌 설계 목표
- 몬스터는 플레이어 추적 X, 항상 Warehouse를 향해 이동
- 목표 검색 로직을 BT(Behavior Tree) 내부에 두지 않고 스폰 시점에 주입
🔁 전체 시스템 흐름
Level → Spawner → Monster → AIController (OnPossess) → Blackboard → Behavior Tree → MoveTo
🧠 구조적 역할 분담
| 구성 요소 | 책임 (Responsibility) |
|---|
| Spawner | 전략적 결정 (목적지 Actor 보유 및 주입) |
| Monster | 데이터 보관 (자신의 목적지 정보 저장) |
| AIController | 데이터 전달 (Pawn의 목적지를 Blackboard로 세팅) |
| BT / Task | 실행 (주어진 키값을 바탕으로 MoveTo 수행) |
3️⃣ [Unreal] 레인 고정 Nav 설계 (디펜스 특화)
- 문제: 기본 NavMesh는 최적 경로를 찾아 옆 레인으로 우회함 → 디자인 붕괴.
- 해결:
NavArea 3개(Left, Mid, Right)와 NavQueryFilter를 생성하여 각 레인별 진입 권한 제한.
- 결과: 몬스터는 자기 레인만 탐색하며, 막히면 우회 대신 장애물을 공격하게 됨.
4️⃣ [Unreal] Wave / DataTable 중심 설계
"로직이 아니라 데이터를 확장하라."
- WaveMetaTable: 라운드 리듬 관리 (Round, PreDelay, Interval)
- WaveSpawnTable: 웨이브 구성 정의 (Type, Rank, Count)
- Type/Rank Table: 몬스터 기본 스탯 및 등급별 배율 보정 단일 진실 소스(SSOT).
5️⃣ [Unreal] Combat & Optimization
⚔️ CombatComponent 통합
AnimNotify 기반으로 애니메이션과 공격 판정 타이밍 일치.
bQueuedApplyDamageThisTick 플래그로 동일 틱 중복 데미지 방지.
📦 Damage Text Pool 설계
- 수많은 데미지 텍스트의 빈번한 생성/삭제로 인한 GC(Garbage Collection) 부하 해결.
- Object Pooling을 통해 프레임 안정성 향상.
🏁 오늘의 공통 구조적 사고 정리
| 구분 | 알고리즘 (Algorithm) | Unreal AI 설계 |
|---|
| 핵심 | 트리 구조 이해 (LCA) | 계층적 시스템 설계 |
| 방식 | 산술적 접근 (부모 노드 찾기) | 데이터 주입 (Injection) |
| 인사이트 | 조건문 제거 | 책임 분리 (Decoupling) |