|
| 1 | +--- |
| 2 | +title: State Tree와 Mass AI 군중 시뮬레이션 |
| 3 | +description: 차세대 AI 시스템 |
| 4 | +author: gemini |
| 5 | +date: 2025-10-14 19:00:00 +09:00 |
| 6 | +categories: [Unreal] |
| 7 | +tags: [AI] |
| 8 | +math: true |
| 9 | +mermaid: true |
| 10 | +--- |
| 11 | + |
| 12 | +#### State Tree - Utility 기반 선택 시스템 |
| 13 | + |
| 14 | +##### Selection Utility Score 개요 |
| 15 | + |
| 16 | +- 상황에 따라 가장 점수가 높은 행동을 선택하게 만드는 시스템 |
| 17 | + |
| 18 | +- 기본 원리 |
| 19 | + - 각 Child State마다 Score 계산 |
| 20 | + - **Weight**를 곱하여 최종 점수 산출 |
| 21 | + - 가장 높은 점수의 State 선택 |
| 22 | +- 주의할 점 |
| 23 | + - Weight만 올려도 효과 없음 |
| 24 | + - Score가 0이면 0 x Weight = 0 |
| 25 | + - 먼저 Score Source를 정의해야 함 |
| 26 | + |
| 27 | + |
| 28 | +##### Score Scource 종류 |
| 29 | + |
| 30 | +- Constant (상수) |
| 31 | + - 고정된 숫자를 Score로 사용 |
| 32 | + - 단순 우선순위 설정 |
| 33 | + - 동적 선택에는 부적합 |
| 34 | +- 동적 값 (진짜 유용한 방식) |
| 35 | + - **HP 퍼센티지** |
| 36 | + - HP 높으면 공격, 낯으면 도망 |
| 37 | + - **Distance** |
| 38 | + - 가까우면 공격, 멀면 순찰 |
| 39 | + - **Context 변수** |
| 40 | + - 런타임 상황에 따른 점수 |
| 41 | + |
| 42 | + |
| 43 | +##### Utility 활용 패턴 |
| 44 | + |
| 45 | +- 기본 공식 |
| 46 | + |
| 47 | +``` |
| 48 | +최종 점수 = Score x Weight |
| 49 | +``` |
| 50 | + |
| 51 | +- 예시 1: HP 기반 선택 |
| 52 | + |
| 53 | +``` |
| 54 | +공격 State : Score = HP% x Weight(1.5) |
| 55 | +도망 State : Score = (1 - HP%) x Weight(2.0) |
| 56 | +
|
| 57 | +HP 80% : 공격 1.2, 도망 0.4 -> 공격 선택 |
| 58 | +HP 20% : 공격 0.3, 도망 1.6 -> 도망 선택 |
| 59 | +``` |
| 60 | + |
| 61 | +- 예시 2: 거리 기반 선택 |
| 62 | + |
| 63 | +``` |
| 64 | +근접 공격 : Score = (1000 - Distance) / 1000 |
| 65 | +원거리 공격 : Score = Distance / 1000 |
| 66 | +
|
| 67 | +Distance 200 : 근접 0.8, 원거리 0.2 -> 근접 선택 |
| 68 | +Distance 800 : 근접 0.2, 원거리 0.8 -> 원거리 선택 |
| 69 | +``` |
| 70 | + |
| 71 | + |
| 72 | +##### Utility vs Transition 비교 |
| 73 | + |
| 74 | +| 방식 | Utility Score | Transition Condition | |
| 75 | +| ----- | ------------- | -------------------- | |
| 76 | +| 선택 기준 | 점수 높은 순 | 조건 만족 여부 | |
| 77 | +| 우선순위 | 동적 계산 | 고정 순서 | |
| 78 | +| 복잡도 | 상황별 가중치 조절 | 명확한 조건 분기 | |
| 79 | +| 적합성 | 연속적 상황 판단 | 명확한 케이스 분리 | |
| 80 | + |
| 81 | +- 사용 기준 |
| 82 | + - **단순하고 명확한 전환** |
| 83 | + - Transition Condition |
| 84 | + - **복잡한 우선순위 계산** |
| 85 | + - Utility Score |
| 86 | + - **연속적인 변수 기반 판단** |
| 87 | + - Utility Score |
| 88 | + |
| 89 | + |
| 90 | +#### Mass AI - Zone Graphs |
| 91 | + |
| 92 | +- Mass AI란? |
| 93 | + - **대규모 군중 시뮬레이션 시스템**으로 Entity Component System (ECS) 아키텍처를 사용 |
| 94 | + |
| 95 | +- 전통적인 AI vs Mass AI |
| 96 | + |
| 97 | +| 구분 | 전통적인 AI | Mass AI | |
| 98 | +| ----- | --------------------- | --------------- | |
| 99 | +| 구조 | 개별 액터 + AI Controller | 경량 Entity + ECS | |
| 100 | +| 적합 규모 | 수십 명 | 수천 명 | |
| 101 | +| 성능 | 개별 처리(느림) | 일괄 처리(빠름) | |
| 102 | + |
| 103 | +- Zone Graph의 개념 |
| 104 | + - **Zone Graph는 NPC의 이동 경로와 영역을 정의하는 내비게이션 시스템** |
| 105 | + - **NavMesh** |
| 106 | + - "어디를 걸을 수 있는가?" |
| 107 | + - **Zone Graph** |
| 108 | + - "어떤 경로를 따라 걸을 것인가?" |
| 109 | + |
| 110 | +- Zone Graph 구성 요소 |
| 111 | + - **Zone Shape (형태)** |
| 112 | + - **Spline**(**스플라인**) |
| 113 | + - 길, 보도, 복도 같은 선형 경로 |
| 114 | + - **Polygon**(**폴리곤**) |
| 115 | + - 광장, 공원, 건물 내부 같은 넓은 영역 |
| 116 | + - **Lanes**(**차선**) |
| 117 | + - 각 Zone Shape 내의 내부 이동 경로 |
| 118 | + - **Width** : 차선의 폭 |
| 119 | + - **Direction** : Forward(전진), Backward(후진), Both(양방향) |
| 120 | + - **Tags** : 접근 권한 제어 |
| 121 | + - **Speed** : 속도 제한 (선택사항) |
| 122 | + - **Tags**(**태그**) |
| 123 | + - NPC 유형과 경로를 연결하는 분류 시스템 |
| 124 | + - `Pedestrian` : 보행자용 경로 |
| 125 | + - `Vehicle` : 차량용 도로 |
| 126 | + - `HighClass` : VIP 전용 구역 |
| 127 | + |
| 128 | +- 태그 시스템 활용 |
| 129 | + - 계층화된 세계 구축 |
| 130 | + |
| 131 | +``` |
| 132 | +일반 농민 -> Pedestrian 태그만 -> 공공 도로만 접근 |
| 133 | +상인 -> Pedestrian + Merchant 태그 -> 상점 내부도 접근 |
| 134 | +귀족 -> All 태그 -> 성과 정원까지 접근 |
| 135 | +``` |
| 136 | + |
| 137 | + |
| 138 | +#### Mass Entity Config Asset |
| 139 | + |
| 140 | +- Config Asset이란? |
| 141 | + - Mass Entity의 설계도 |
| 142 | + - Blueprint가 액터를 정의하듯, Config Asset은 Mass 엔티티를 정의 |
| 143 | + |
| 144 | +- 핵심 개념 |
| 145 | + - **Fragments**(**프래그먼트**) |
| 146 | + - 엔티티가 보유하는 데이터 조각 |
| 147 | + - **Transform Fragment** : 위치와 회전 |
| 148 | + - **Velocity Fragment** : 속도 |
| 149 | + - **Health Fragment** : 체력 |
| 150 | + - **Traits**(**특성**) |
| 151 | + - 엔티티에 기능을 추가하는 모듈 |
| 152 | + - **Movement Trait** : 이동 기능 |
| 153 | + - **Avoidance Trait** : 충돌 회피 |
| 154 | + - **Animation Trait** : 애니메이션 |
| 155 | + - **Processors**(**프로세서**) |
| 156 | + - Fragments를 처리하고 업데이트하는 시스템 |
| 157 | + |
| 158 | +- Traits와 Fragments의 관계 |
| 159 | + |
| 160 | +``` |
| 161 | +Movement Trait 추가 |
| 162 | + ↓ |
| 163 | +자동으로 추가되는 Fragments: |
| 164 | + - Transform Fragment |
| 165 | + - Velocity Fragment |
| 166 | + - Movement Parameters Fragment |
| 167 | + ↓ |
| 168 | +Movement Processor 활성화 |
| 169 | +``` |
| 170 | + |
| 171 | +- 모듈식 설계의 장점 |
| 172 | + - 필요한 기능만 선택적 추가 |
| 173 | + - 메모리 효율성 극대화 |
| 174 | + - 다양한 NPC 유형 쉽게 생성 |
| 175 | + |
| 176 | +- 자동으로 작동하는 시스템들 |
| 177 | + - Config Asset에서 추가한 Traits 덕분에 |
| 178 | + - **Avoidance Trait** : 다른 NPC와 충돌 예측 및 회피 |
| 179 | + - **Movement Trait** : 부드러운 이동 처리 |
| 180 | + - **Steering Trait** : 자연스러운 회전 |
| 181 | + - **Navigate Obstacle Trait** : 장애물 우회 |
| 182 | + ***추가 코드 없이 자동으로 작동!*** |
| 183 | + |
| 184 | + |
| 185 | +#### Sync (동기화) |
| 186 | + |
| 187 | +- Sync란? |
| 188 | + - Mass Entity(데이터)와 Visual Actor(3D 캐릭터) 사이의 정보 동기화 |
| 189 | + |
| 190 | +``` |
| 191 | +Mass Entity (두뇌) |
| 192 | + ↕ Sync |
| 193 | +Visual Actor (몸) |
| 194 | +``` |
| 195 | + |
| 196 | +- 동기화 방향 |
| 197 | + - **Mass to Actor** : Mass 계산 -> 액터 적용 (가장 일반적) |
| 198 | + - **Actor to Mass** : 액터 상태 -> Mass 전달 |
| 199 | + - **Both Ways** : 양방향 동기화 |
| 200 | + |
| 201 | +- 예시 |
| 202 | + - Agent Movement Sync (Mass to Actor) |
| 203 | + |
| 204 | + ``` |
| 205 | + Mass가 새 위치 계산 -> Visual Actor를 그 위치로 이동 |
| 206 | + ``` |
| 207 | + |
| 208 | + - Player Navigation Obstacle (Actor to Mass) |
| 209 | + |
| 210 | + ``` |
| 211 | + 플레이어 이동 -> Mass 시스템에 위치 알림 -> NPC가 회피 |
| 212 | + ``` |
| 213 | + |
| 214 | + |
| 215 | +#### Wander (배회) State 구현 |
| 216 | + |
| 217 | +- Wander의 두 단계 |
| 218 | + - **목표 찾기** : 어디로 갈지 결정 |
| 219 | + - **이동하기** : 그곳까지 경로 따라 이동 |
| 220 | + |
| 221 | +- Task 구성 |
| 222 | + - Task 1 : ZG Find Wander Target |
| 223 | + |
| 224 | + ``` |
| 225 | + 현재 위치에서 Zone Graph 검색 |
| 226 | + ↓ |
| 227 | + 태그 필터링 (Pedestrian, HighClass) |
| 228 | + ↓ |
| 229 | + 무작위 지점 선택 |
| 230 | + ↓ |
| 231 | + Output : Wander Target Location |
| 232 | + ``` |
| 233 | + |
| 234 | + - Task 2 : ZG Path Follow |
| 235 | + |
| 236 | + ``` |
| 237 | + Input : Wander Target Location (Task 1의 출력) |
| 238 | + ↓ |
| 239 | + 경로 계산 |
| 240 | + ↓ |
| 241 | + 경로 따라 이동 |
| 242 | + ``` |
| 243 | + |
| 244 | +- Transition 설정 |
| 245 | + - On State Completed -> Transition to Root |
| 246 | + |
| 247 | + ``` |
| 248 | + Wander 완료 -> Root로 돌아가기 -> Wander 재시작 -> 무한 반복 |
| 249 | + ``` |
| 250 | + |
| 251 | + |
| 252 | +#### Mass AI 디버깅 |
| 253 | + |
| 254 | +- 디버그 명령어 (게임 내 \` 키) |
| 255 | + - **기본 뷰** : Mass 데이터 + 위치 |
| 256 | + - **Shift + V** : 속도, 상태 등 추가 정보 |
| 257 | + - **Shift + O** : 회피 (Avoidance) 시각화 |
| 258 | + - **Shift + C** : 경로 (Zone Graph) 표시 |
| 259 | + - **Shift + S** : Shape 표시 |
| 260 | + |
| 261 | +- 시각적 요소 |
| 262 | + - **원** : Mass 엔티티 위치 |
| 263 | + - **메시** : Visual Actor 위치 |
| 264 | + - **화살표** : 이동 방향과 의도 |
| 265 | + - **노란색 선** : 목표 방향 (Smooth Orientation) |
| 266 | + - **작은 선들** : 회피 벡터 |
| 267 | + - **Maroon 화살표** : 원하는 목적지 |
| 268 | + |
| 269 | + |
| 270 | +#### 플레이어 - NPC 상호작용 |
| 271 | + |
| 272 | +- 문제 |
| 273 | + - NPC는 다른 Mass 엔티티만 인식 |
| 274 | + - 플레이어는 Mass 엔티티가 아님 |
| 275 | + - 결과 : NPC가 플레이어를 "보지 못한" |
| 276 | + |
| 277 | +- 해결 : Navigation Obstacle |
| 278 | + - 플레이어를 Mass 시스템에 등록 |
| 279 | + |
| 280 | + ``` |
| 281 | + Player Config Asset 생성 |
| 282 | + ↓ |
| 283 | + Traits 추가 |
| 284 | + - Agent Capsule Collision Sync (Actor to Mass) |
| 285 | + - Navigation Obstacle |
| 286 | + ↓ |
| 287 | + 플레이어 위치를 매 프레임 Mass에 전달 |
| 288 | + ↓ |
| 289 | + NPC가 플레이어를 회피 |
| 290 | + ``` |
0 commit comments