티스토리 뷰
🟩 학습 목표
- AI Controller, Behavior Tree, Blackboard의 역할과 연동 프로세스 이해 및 기초 에셋 구축
- NavMeshBoundsVolume의 런타임 생성 모드별 차이를 이해하고, Navigation Invoker를 통해 연산 리소스 최적화
- MoveTo 함수 계열의 메커니즘을 파악하고, NavModifierVolume 및 RVO(Reciprocal Velocity Obstacles)를 활용하여 정적/동적 예외 처리 로직 구현
- AIPerception 시야 시스템과 거리 기반 계층 구조를 C++로 코딩하여 플레이어를 추적하는 AI 제어 시스템 완성
🟧 1. Unreal Engine AI 핵심 3인방 아키텍처
언리얼 엔진의 AI 시스템은 생성형 모델과 달리 상태와 조건에 따라 논리적으로 움직이는 상태 머신 및 의사결정 구조를 기반으로 작동한다. 핵심 오브젝트는 다음과 같이 분할된다.
- AI Controller (C++): AI 액터의 두뇌 및 신경망 역할을 담당하며 신체를 조작하고 빙의(Possess)한다.
- Behavior Tree (Editor): 어떤 상황에 무슨 행동을 할지 결정하는 실행 규칙 및 판단 알고리즘(의사결정나무)을 정의한다.
- Blackboard (Editor): AI가 의사결정에 필요한 데이터, 상태 값, 키(Key) 변수들을 저장하고 공유하는 데이터 저장소 역할을 한다.
🟧 2. 네비게이션 메시 환경 구축 및 리소스 최적화
🟦 Runtime Generation 모드별 분석
AI의 이동 가능 영역을 정의하는 NavMeshBoundsVolume은 프로젝트의 성격에 따라 런타임 생성 옵션을 다르게 가져가야 한다.
| 생성 모드 | 작동 방식 및 특징 | 장단점 |
| Static | 오프라인(에디터 빌드)에서 생성 후 저장된다. | 연산 비용이 제로에 가깝지만, 실시간 지형 변화를 무시한다. |
| Dynamic | 런타임 중 데이터가 변경되면 해당 타일의 메시를 실시간 재생성한다. | 동적 지형물 파괴 등에 즉각 대응하나, 하드웨어 소모량이 매우 크다. |
| Dynamic Modifiers Only | 오프라인에서 빌드하되, 런타임에는 메시의 일부 영역 삭제/링크 수정만 수행한다. | 표면 자체를 새로 생성하지 않고 캐시를 재활용하여 타일 비용을 최대 50% 절감한다. |
🟦 Navigation Invoker 기반 동적 연산 최적화
지오메트리 브러시(Brush)의 특성상 NavMeshBoundsVolume 자체를 런타임 중에 크기를 늘리거나 동적 생성하는 것은 언리얼 아키텍처 구조상 불가능하다. 오픈월드나 대규모 맵에서 발생하는 연산 비효율을 해결하기 위해 Navigation Invoker 컴포넌트를 활용한다. 액터 주변의 지정된 반경만 네비메시를 생성하고 외곽은 삭제하여 CPU 리소스를 절약한다.
// Build.cs 모듈 추가 필수
PublicDependencyModuleNames.AddRange(new string[] { "NavigationSystem" });
// SCC_UEAICharacter.cpp 생성자 구현 부분
#include "NavigationInvokerComponent.h"
ASCC_UEAICharacter::ASCC_UEAICharacter()
{
NavGenerationRadius = 1000.0f;
NavRemovalRadius = 1500.0f;
// 네비게이션 인보커 생성 및 반경 셋업
NavInvoker = CreateDefaultSubobject<UNavigationInvokerComponent>(TEXT("NavInvoker"));
NavInvoker->SetGenerationRadii(NavGenerationRadius, NavRemovalRadius);
}
🟧 3. 경로 탐색 알고리즘 응용 및 MoveTo 메커니즘
🟦 A* 기반 최저 비용 경로 탐색 공식
언리얼 엔진의 경로 탐색(Pathfinding)은 폴리곤 간의 가중치를 계산하여 가장 낮은 비용이 발생하는 경로를 최우선으로 채택하는 "낮은 가격순" 원리로 작동한다.
🟦 NavModifierVolume을 이용한 동적 경로 제어
런타임에 네비메시 브러시를 수정할 수 없으므로, 대신 NavModifierVolume의 위치를 실시간으로 변경하여 AI의 경로를 우회시킨다. NavArea_Obstacle 클래스를 지정하면 해당 볼륨 영역의 통과 비용이 극도로 높아지므로 AI가 실시간으로 다른 최적 경로를 찾아 선회한다.
🟦 MoveToLocation vs MoveToActor
AIController 내부 이동 함수는 목적지의 속성에 따라 두 가지로 분리된다.
- MoveToLocation: 고정된 정적 위치 벡터(FVector) 좌표를 향해 이동한다.
- MoveToActor: 동적 무버블 객체(AActor)를 타겟으로 삼는다. 타겟이 실시간으로 이동할 경우 위치를 매 프레임 업데이트하여 추적하므로 Location 방식보다 연산 비용이 더 발생한다.
🟧 4. RVO(Reciprocal Velocity Obstacles) 동적 회피
🟦 RVO 시스템의 메커니즘
정적 장애물을 우회하는 Pathfinding과 달리, RVO는 움직이는 다수의 액터가 서로의 속도와 방향 벡터를 실시간으로 계산하여 충돌을 회피하는 로직이다. 경로의 재계산(Re-pathfinding) 없이 작동하므로 다인칭 병목 구간에서 자연스러운 움직임을 보장한다.
// RVO_Character.cpp 초기화 설정
#include "GameFramework/CharacterMovementComponent.h"
ARVO_Character::ARVO_Character()
{
UCharacterMovementComponent* MovementComponent = GetCharacterMovement();
if (MovementComponent)
{
MovementComponent->bUseRVOAvoidance = true; // RVO 활성화
MovementComponent->AvoidanceConsiderationRadius = 300.f; // 감지 반경
MovementComponent->AvoidanceWeight = 0.5f; // 가중치 (우선순위 계급)
}
}
- RVO를 비활성화(false)하면 다수의 AI가 정면충돌할 때 서로의 경로를 완전히 차단해 버리는 병목 락(Lock) 현상이 발생한다.
🟧 5. AIPerception 시야 인지 및 계층적 플레이어 추적 시스템
단순 틱 타일의 거리 계산은 부하를 유발하므로 UAISenseConfig_Sight 인지 시스템과 EAIState 상태 머신을 결합하여 정교한 추적 시퀀스를 구현한다.
🟦 계층형 인지 상태 머신 구현
- Idle (대기): 플레이어가 감지 반경 밖에 있는 상태이다.
- Suspicious (의심): DetectionRadius 내에 들어와 시야에 포착되었으나 아직 추격 반경 외곽에 있어 경계하는 상태다.
- Chasing (추격): ChaseRadius 내부에 진입하여 플레이어를 타겟 액터로 고정하고 MoveToActor를 지속 실행하는 상태다. LoseInterestRadius를 넘어가면 추격을 중단한다.
// Chaser_AIController.cpp 핵심 전이 로직 및 시야 상실 예외 처리
void AChaser_AIController::OnPerceptionUpdated(AActor* Actor, FAIStimulus Stimulus)
{
ACharacter* PlayerCharacter = UGameplayStatics::GetPlayerCharacter(GetWorld(), 0);
if (Actor != PlayerCharacter) return;
if (Stimulus.WasSuccessfullySensed()) // 시야 감지 성공 시
{
TargetActor = Actor;
float Distance = FVector::Dist(GetPawn()->GetActorLocation(), Actor->GetActorLocation());
if (Distance <= DetectionRadius)
{
if (Distance <= ChaseRadius) StartChasing(Actor);
else CurrentState = EAIState::Suspicious;
}
}
else // 시야에서 플레이어가 사라졌을 때 (유실)
{
if (CurrentState == EAIState::Chasing)
{
// 마지막으로 타겟이 목격된 맵의 좌표로 최종 이동을 명령하여 영리한 AI 연출
MoveToLocation(LastKnownLocation, 50.0f);
CurrentState = EAIState::Suspicious;
}
}
}
🟦 자동 네비게이션 링크 생성 (RecastNavMesh Auto Link)
언리얼 엔진 5.5부터 고도화된 기능으로, 물리적으로 네비메시가 끊어진 도랑이나 절벽 지형을 에디터가 자동 분석하여 링크를 연결한다. AI 캐릭터가 끊긴 지점에 도달하면 NavLinkProxy 이벤트를 받아 Z축 점프 로직을 작동시킴으로써 복합 입동 경로를 돌파할 수 있게 제어한다.
🟧 핵심 요약
- 언리얼 AI 아키텍처는 AIController(제어), Behavior Tree(판단), Blackboard(기억)의 삼각 구조로 유기적으로 맞물려 돌아간다.
- 네비메시는 Runtime Generation -> Dynamic 설정을 통해 동적으로 수정 가능하나, 맵 전체 적용 시 부하가 크므로 반드시 Navigation Invoker를 연동하여 연산 범위를 제한해야 한다.
- 런타임에 브러시 구조를 변경할 수 없는 한계는 NavModifierVolume의 이동과 비용 가중치 변조를 통해 우회 제어가 가능하다.
- 움직이는 동적 장애물 및 AI 간 병목 현상은 RVO Avoidance 컴포넌트 옵션을 통해 연산 부하 없이 실시간 벡터 회피로 해결한다.
- 정교한 추적 AI 설계 시 시야(AIPerception) 컴포넌트를 부착하고, 거리 변수를 Detection < Chase < LoseInterest 계층 구조로 나누어 코딩해야 상태 전이의 예외 에러가 발생하지 않는다.
'내일배움캠프 Unreal_7기 > 본캠프' 카테고리의 다른 글
| 게임플레이 태그 기반 인벤토리 C++ 아키텍처 및 코어 로직 구현 (0) | 2026.05.27 |
|---|---|
| 캐릭터 상태 제어 리팩토링 및 멀티플레이 동기화 (0) | 2026.05.26 |
| 캐릭터 이동 메커니즘 개선 및 모션 매칭 적용 (0) | 2026.05.21 |
| 나이아가라 공격 궤적 이펙트 만들기 (0) | 2026.04.14 |
| Property Replication (1) | 2026.03.23 |

