언리얼 AI 시스템을 만들면서 1주일을 보내고 있습니다.
그동안 TIL작성도 없이 개발에만 몰두했습니다.
지금 올리는 이 글은 TIL이 아닌 WIL입니다.
현재 진행중인 에디터유틸리를 이용한 레벨에 편의 기능 작업 중


TIL (Today I Learned) – Dynamic AI System (DAS) 코드 구조와 개념 정리



1. 시스템 동작 메커니즘 및 사용 기술/알고리즘
1.1 전체 메커니즘 개요
- 월드 레벨
- UDASWorldSubsystem이 월드에 존재하는 모든 PathPoint, ActionPoint를 전역 관리합니다.
- 에디터 상에서 ADASMapStreetPath(Spline)와 ADASPathSpot을 통해 여러 지점을 자동 생성/연결할 수 있습니다.
- AI 캐릭터
- AI 캐릭터(또는 Pawn)는 UDASComponent를 소유하여 DAS 로직을 실행합니다.
- Init(UBehaviorTree*)가 호출되면 Behavior Tree와 연계되어 ‘PathPoint 이동 → ActionPoint 실행 → 다음 지점 이동’ 과정을 제어합니다.
- PathPoint & ActionPoint
- PathPoint(ADASPathPoint)는 AI가 이동할 지점(Spot 여러 개 가능).
- ActionPoint(ADASActionPoint)는 실제 액션(애니메이션 재생, 함수 호출 등)을 모아둔 지점.
- 두 지점에는 ConditionQuery가 붙어, “이 지점이 현재 실행 가능한가?”를 판단(쿨다운, 특정 태그/상태 등).
- ConditionQuery & ActionSelector
- UDASConditionQuery: 여러 UDASCondition(추상 객체)을 AND/OR 형태로 묶어, 현재 상태 충족 여부를 종합.
- Observer 패턴: OnConditionResultChanged 델리게이트로 조건이 실시간 변하면 AI 로직도 갱신 가능.
- UDASActionSelector: 특정 PathPoint에 붙여 “해당 지점 도착 시 어느 ActionPoint들을 선택해 실행할 것인지”를 커스텀 로직으로 결정.
- UDASConditionQuery: 여러 UDASCondition(추상 객체)을 AND/OR 형태로 묶어, 현재 상태 충족 여부를 종합.
- 실행 흐름
- RunMode가 ExecutePathPoints인 경우:
- ADASComponent가 ActivePathPoint로 이동 → 해당 지점의 ActionSelector로 액션포인트 큐를 구성 → 순차 실행 → 다음 PathPoint로 이동.
- RunMode가 ExecuteActionsFromSelector인 경우:
- ActionSelector가 반환해주는 특정 ActionPoint들만 집중 실행 (순회 방식과는 별개).
- RunMode가 ExecutePathPoints인 경우:
- 비동기 실행
- UAsyncActionHandlePointExecution, UAsyncActionHandleActionExecution 두 가지 Async Node를 두어, 블루프린트에서 “액션 완료 시점”을 이벤트로 처리 가능.
- 내부적으로 AsyncExecute(비동기) → 완료 시 OnFinished 콜백 → 결과(성공/실패) 처리.
3.2 관련 기술 및 알고리즘
- Unreal Subsystem
- UWorldSubsystem: 월드 단위 싱글턴처럼 동작하여, 전역 리소스(PathPoints/ActionPoints) 캐싱 및 제공.
- 반복적으로 GetAllActorsOfClass를 호출하는 것보다 월등히 효율적.
- Condition 시스템(Observer 패턴)
- UDASCondition: 추상 클래스. 각종 조건(체력, 태그 보유, 시간대, 쿨다운 등)에 맞춰 확장 가능.
- UDASConditionQuery: 여러 UDASCondition을 합치는 래퍼 객체. Fulfilled 여부가 바뀌면 OnConditionResultChanged로 알림.
- AND/OR 연산자( EDASOperator )로 조건을 조합 → AI는 이를 수신해 행동을 바꾼다.
- Path Solver / Graph 탐색
- ADASPathPoint가 NextPathPoints / PreviousPathPoints로 그래프 형태를 이룬다.
- 기본은 단순히 배열 중 무작위/순차로 다음 경로를 골라 이동하지만,
- UDASPathSolver를 확장하면(예: A*나 Dijkstra 구현) 복잡한 경로 탐색도 가능.
- Behavior Tree & Blackboard
- UDASComponent::Init(UBehaviorTree*)에서 AIController->RunBehaviorTree 실행.
- Blackboard 키(GoalLocation, GoalRotation, PathPoint, ActionPoint 등)를 매번 갱신해 BT의 Task 또는 Decorator가 활용.
- AI 이동은 MoveTo 노드가 GoalLocation(또는 PathPoint) 참조.
- 비동기 액션 처리
- UDASAction: “Play Montage”, “Wait n seconds”, “Call Function” 등 구현체가 다양.
- Async 노드(UAsyncActionHandleActionExecution)로 “액션 실행 → 완료/실패 대기” 블록을 블루프린트에서 직관적으로 구성.
- 에디터 확장 & 디버깅
- UDASDeveloperSettings: 디버그 Draw(Line/Sphere/Arrow) 거리, 갱신 주기, 색상 등을 세팅.
- DrawDebug 함수들(ADASBasePoint::DrawDebug, UDASPointVisComponent, UDASVisComponent)로 에디터/런타임에서 시각화.
- ADASMapStreetPath, ADASPathSpot은 스플라인 편집 시 자동 Spot 액터를 생성하여 PathPoint를 빠르게 배치(레벨 디자이너 편의성).
정리
**Dynamic AI System(DAS)**는 언리얼 엔진의 Subsystem, Behavior Tree & Blackboard, Condition Observer 패턴, Async Actions 등 다양한 기능을 결합해 “경로 기반 이동” + “액션 포인트 실행” 로직을 모듈화 한 구조입니다.
- UWorldSubsystem(UDASWorldSubsystem) : 전역적으로 PathPoint/ActionPoint 등록 & 검색
- DASComponent(UDASComponent) : AI Pawn/Character에 붙어 “어떤 경로 지점으로 이동할지, 액션은 어떤 순서로 실행할지”를 통합 관리
- PathPoint & ActionPoint : 맵 곳곳에 배치되어, AI가 순회하거나 액션을 수행하는 실제 지점
- ConditionQuery : 실행 가능 여부를 동적으로 감지(쿨다운, 조건 충족 등)
- ActionSelector : “경로 지점에 도착했을 때 어떤 액션 포인트를 사용할지” 결정
- Async Action : 액션 실행이 완료될 때까지 비동기로 대기, 간단한 이벤트 바인딩 구조 제공
이로써 AI가 “지점 간 이동 → 행동 → 다시 이동”을 유연하게 제어할 수 있고, 재사용 및 확장성을 높일 수 있게 됩니다.
디자이너/프로그래머는 Path/Action/Condition/Solver/Selector를 각각 필요에 맞춰 확장 구현하고, Behavior Tree와 매끄럽게 연동하여 다양한 AI 시나리오를 구현할 수 있습니다.
아래는 가이드 문서입니다.
1. DASWorldSubsystem
- 역할: 월드에 존재하는 모든 ADASPathPoint(경로 지점)과 ADASActionPoint(액션 지점)를 전역적으로 관리하는 서브시스템.
- 사용 의의:
- 매번 GetAllActorsOfClass를 호출하기보다, AddPathPoint/RemovePathPoint, AddActionPoint/RemoveActionPoint로 등록/해제함으로써 성능을 최적화.
- AI가 특정 지점(PathPoint/ActionPoint)을 찾을 때도 서브시스템의 캐시를 사용 (FindPathPointById, FindActionPointById 등).
2. DASTypes
- EDASRunMode / EDASPathBehavior / EDASExecutionResult 등 각종 열거형(Enums) 정의.
- AI의 실행 모드(경로 기반 혹은 액션 선택자 기반), 행동(경로 이동/액션 실행) 등 상태나 결과를 표현하는 값.
- FDASSpot, FDASActionSelectorWrapper, FDASComponentSnapshot 같은 구조체(Struct)도 함께 선언:
- FDASSpot: PathPoint 주변에 여러 Spot이 있고, AI가 정확히 그 위치(회전 포함)에 배치되도록 관리.
- FDASComponentSnapshot: 저장/로드 기능을 위한 AI 상태 스냅샷 구조체(액션 큐, 실행 모드, 위치 등).
3. DASBluePrintFunctionLibrary
- 기능: Blueprint에서 호출 가능하도록 만든 여러 유틸리티 함수 모음.
- 주요 함수 예시:
- CallFunctionByName: 문자열로 함수를 찾아 호출.
- ClearTimersAndDelays: 특정 UObject가 사용 중인 타이머/Latent 액션(Delay 등)을 한 번에 정리.
- SortPathPointsByDistance, SortActionPointsByDistance: 주어진 배열을 특정 위치와의 거리 기준으로 정렬.
- FilterOutTakenActionPoints: 이미 다른 AI가 사용 중(taken)인 액션 포인트를 필터링.
4. DASAsyncNodes (UAsyncActionHandlePointExecution / UAsyncActionHandleActionExecution)
- BlueprintAsyncActionBase를 상속받아, “Async”(비동기) 노드 형태로 액션 포인트를 실행.
- ExecuteActionPoint / ExecuteAction 두 가지 방식:
- ExecuteActionPoint: ADASActionPoint를 비동기 실행 후 완료 결과(성공/실패)를 OnFinished로 반환.
- ExecuteAction: 개별 UDASAction 단위로 동일한 방식 수행.
- 의의: 블루프린트에서 비동기 플로우(Async) 노드로 만들어, “Action이 끝나길 대기→다음 노드” 식의 직관적인 그래프 구성 가능.
5. ADASPathPoint / ADASActionPoint
- ADASPathPoint(경로 포인트)
- AI가 이동할 지점을 구성하는 액터.
- NextPathPoints / PreviousPathPoints로 전/후진 경로가 연결되며, 경로 탐색 시 참고.
- bReturnToPathPointAfterExecutingActions: 액션 수행 뒤 원래 지점으로 복귀할지 여부 등 옵션.
- 여러 Spot(FDASSpot)을 가지고 있을 수 있어, AI가 PathPoint에 도달 시 정확히 어느 위치(Spot)로 배치될지 결정.
- ADASActionPoint(액션 포인트)
- Actions 배열을 가진 액터로, AI가 이 지점에 도달해 지정된 행동(몬타주 재생, 함수 호출 등)을 순차 실행.
- “IsTaken” 상태로 여러 AI가 동시에 접근 못 하게 관리(“빼앗겼는지”를 확인).
- 쿨다운(Cooldown)도 존재하여, 일정 시간 동안 재실행을 막을 수도 있음.
6. DASBasePoint
- ADASPathPoint / ADASActionPoint의 부모 추상 클래스.
- 공통 속성: PointId(GUID 식별자), ConditionQuery(조건), MoveSpeed, bRotateToPoint 등.
- 주요 메서드:
- CanRun(): 이 포인트가 사용 가능한지(조건 충족/쿨다운 등)를 체크.
- DrawDebug(): 에디터나 디버그 모드에서 지점 시각화(라인, 아이콘, 텍스트 등).
7. DASCondition & DASConditionQuery
- UDASCondition: “특정 조건”을 하나만 담당(예: 체력, 태그 보유 여부 등).
- 내부적으로 IsConditionFulfilled_Internal을 구현해 조건 부합 여부를 판단.
- OnConditionResultChanged 델리게이트를 통해 실시간 상태 변경 알림.
- UDASConditionQuery: 여러 Condition들을 묶어 종합 결과를 확인(AND / OR 연산 등).
- Initialize()로 각각의 Condition을 세팅/이벤트 등록.
- IsConditionFulfilled() 호출 시 내부 Condition들의 결과를 종합.
- OnConditionResultChanged 브로드캐스트로 “전체 조건 상태가 바뀐” 시점에 알림.
8. DASAction & DASActionSelector
- UDASAction:
- 액션 포인트 내부에 들어가는 “실행 단위” 객체.
- Execute() → 비동기 완료( FinishExecute() ) 흐름.
- 예: 애니메이션 재생, 대기, 함수 호출 등 다양하게 블루프린트에서 확장 가능.
- UDASActionSelector:
- 경로 포인트(ADASPathPoint)에 붙어서 “어떤 액션 포인트들을 실행할지” 결정하는 로직을 담당.
- 예: GetActionPointsToExecute를 오버라이드하여, 태그 필터나 무작위 선택 등 커스텀.
- “Instanced” 되어 PathPoint마다 별도 인스턴스(커스텀 로직) 사용 가능.
9. DASComponent
- AI Pawn/Character에 붙는 핵심 컴포넌트.
- RunMode(경로 기반 / 액션 선택자 기반)를 바탕으로 AI 동작 전체를 제어.
- BehaviorTree와 연결하여:
- PathPoint 이동(ActivePathPoint)
- 액션 포인트(ActionPointsQueue) 실행
- 다음 PathPoint 이동 ...
- 상태: PathBehavior(경로 이동 중인지, 액션 중인지 등), bIsMovingForwardAlongPath(앞/뒤 이동) 등.
- 스냅샷(FDASComponentSnapshot) 기능으로 현재 상태를 저장/로드 가능 → 세이브/로드나 AI 풀링(오브젝트 풀)에 유용.
10. DASMapStreetPath / DASPathSpot
- 스플라인을 이용해 지도(도로) 경로를 구성하는 액터(ADASMapStreetPath).
- 에디터에서 Spline을 편집하면, 각 포인트마다 ADASPathSpot을 자동 생성/동기화.
- ADASPathSpot에서 “SpawnDASBasePoint(예: ADASPathPoint)” 버튼으로 PathPoint를 에디터 상에서 생성.
- Spot 간 연결(Next/Previous)을 자동 세팅해서, 실제 경로(ADASPathPoint)를 빠르게 만들 수 있음.
오늘 배운 핵심 정리
- DASWorldSubsystem이 전역으로 PathPoint/ActionPoint를 캐싱해둬서 AI가 손쉽게 참조 가능.
- DASComponent는 AI의 전체 흐름(경로 이동, 액션 실행, 스냅샷 관리)을 담당하고 Behavior Tree와 연동.
- PathPoint vs. ActionPoint:
- PathPoint는 ‘이동 지점’, ActionPoint는 ‘행동 지점’.
- 둘 다 Condition(쿨다운/태그 등)으로 실행 가능 여부를 제어하고, Spot을 통해 세밀한 위치 지정 가능.
- DASConditionQuery로 여러 조건을 묶고, AND/OR로 종합 판단.
- UDASAction / ActionSelector로 액션 로직을 확장 가능 (비동기 실행/완료).
- Debug & Editor:
- DrawDebug 계열 함수와 VisComponent로 에디터/런타임에 시각화 지원.
- DASDeveloperSettings에서 디버그 옵션(표시 거리, 화살표 애니메이션 등) 제어

'UnrealCamp' 카테고리의 다른 글
| 10주차 Day3- Unreal Engine C++로 Enemy AI Base 구현하기 (0) | 2025.02.19 |
|---|---|
| 10주차 Day2 AEnemyAIController로 적 AI 상태 제어하기 (0) | 2025.02.18 |
| 7주차 Day4 [캐릭터 #2 코스메틱] (0) | 2025.01.30 |
| 7주차 Day2 [Lyra Input] (0) | 2025.01.28 |
| 3주차 Day1 STL (0) | 2024.12.30 |