PART 5 - 강의 1/3

NavMesh 생성과 설정

RecastNavMesh의 생성 과정, NavMeshBoundsVolume, Agent 파라미터 설정을 심화 학습합니다

01

Recast NavMesh 아키텍처

UE5 Navigation Mesh의 내부 구조

UE5는 Recast/Detour 라이브러리를 기반으로 NavMesh를 생성합니다. 월드의 지오메트리를 분석하여 AI가 이동 가능한 영역을 다각형 메시로 표현하며, Detour가 이 메시 위에서 경로 탐색을 수행합니다.

NavMesh 생성 파이프라인
Geometry 수집 Voxelization Region 생성 Contour 추출 Polygon Mesh
C++// ARecastNavMesh - UE5의 NavMesh 액터 // 레벨에 NavMeshBoundsVolume을 배치하면 자동 생성 // 핵심 생성 파라미터 (RecastNavMesh 프로퍼티) // Agent Radius: AI 캡슐 반지름 (기본 35) // Agent Height: AI 캡슐 높이 (기본 144) // Agent Max Slope: 올라갈 수 있는 최대 경사 (기본 44도) // Agent Max Step Height: 올라갈 수 있는 단차 (기본 35) // Cell Size: 복셀 셀 크기 (기본 19) // 작을수록 정밀하지만 메모리/시간 증가 // Cell Height: 복셀 높이 (기본 10) // Tile Size: NavMesh 타일 크기 // 동적 NavMesh 시 타일 단위로 업데이트 // 접근 방법 UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(GetWorld()); ANavigationData* NavData = NavSys->GetDefaultNavDataInstance(); ARecastNavMesh* RecastNavMesh = Cast<ARecastNavMesh>(NavData); // NavMesh 빌드 상태 확인 bool bIsBuilding = NavSys->IsNavigationBuildInProgress(); bool bHasData = NavSys->GetDefaultNavDataInstance() != nullptr;
구조

Cell Size는 NavMesh 정밀도를 결정합니다. Agent Radius의 절반 정도가 적당합니다. 너무 작으면 빌드 시간과 메모리가 급증하고, 너무 크면 좁은 통로를 인식하지 못합니다.

02

NavMeshBoundsVolume과 빌드 설정

NavMesh 생성 영역 설정

NavMeshBoundsVolume은 NavMesh가 생성될 영역을 정의합니다. 볼륨 내부의 지오메트리만 NavMesh로 변환되므로, 게임플레이 영역에 맞게 배치해야 합니다.

C++// NavMeshBoundsVolume 배치 // 1. 레벨에 NavMeshBoundsVolume 추가 // Place Actors → Volumes → NavMeshBoundsVolume // 2. 게임플레이 영역 전체를 감싸도록 크기 조절 // 3. Build → Build Paths 또는 자동 빌드 // Runtime Generation 설정 // Project Settings → Navigation System // - Runtime Generation: // Static: 에디터에서만 빌드 (최적 성능) // Dynamic: 런타임에 동적 빌드 // DynamicModifiersOnly: Modifier만 동적 적용 // Navigation System 설정 // - bAllowClientSideNavigation: 클라이언트에서도 NavMesh // - bAutoCreateNavigationData: 자동 NavData 생성 // 다중 Agent 지원 // Project Settings → Navigation System → Agents // Agent 1: 일반 NPC (Radius=35, Height=144) // Agent 2: 큰 보스 (Radius=100, Height=300) // Agent 3: 작은 동물 (Radius=15, Height=50) // 각 Agent 마다 별도 NavMesh 생성됨 // 메모리: Agent 수 * NavMesh 크기 // Supported Agents 설정 // RecastNavMesh의 Navigation Data 생성 시 // 어떤 Agent를 지원할지 설정 UPROPERTY(config, EditAnywhere) FNavDataConfig NavDataConfig; // NavDataConfig.DefaultQueryExtent: 쿼리 허용 범위 // NavDataConfig.AgentRadius / AgentHeight
주의

다중 Agent 설정 시 NavMesh가 Agent 수만큼 생성됩니다. Agent가 3종이면 메모리 사용량이 3배가 되므로, 크기가 비슷한 Agent는 하나로 통합하는 것이 좋습니다.

03

경로 탐색과 Path Following

A* 경로 탐색과 Path Following Component

경로 탐색은 Detour의 A* 알고리즘으로 수행되며, UPathFollowingComponent가 경로를 따라 Pawn을 이동시킵니다. 경로는 NavMesh 폴리곤의 포인트 시퀀스로 표현됩니다.

C++// 경로 탐색 요청 UNavigationSystemV1* NavSys = UNavigationSystemV1::GetCurrent(GetWorld()); // 동기 경로 탐색 FPathFindingQuery Query( AIController, // 요청자 *NavSys->GetDefaultNavDataInstance(), StartLocation, GoalLocation); FPathFindingResult Result = NavSys->FindPathSync(Query); if (Result.IsSuccessful()) { // Result.Path: 경로 포인트 배열 for (const FNavPathPoint& Point : Result.Path->GetPathPoints()) { FVector Loc = Point.Location; // ... } } // 비동기 경로 탐색 (권장) NavSys->FindPathAsync( FNavAgentProperties(), Query, FNavPathQueryDelegate::CreateUObject( this, &AMyAIController::OnPathFound)); // AIController의 MoveToLocation/MoveToActor // 내부적으로 경로 탐색 + Path Following 수행 FAIMoveRequest MoveReq; MoveReq.SetGoalLocation(TargetLocation); MoveReq.SetAcceptanceRadius(50.f); MoveReq.SetUsePathfinding(true); MoveReq.SetAllowPartialPath(true); // 부분 경로 허용 AIController->MoveTo(MoveReq); // Path Following 상태 감시 AIController->GetPathFollowingComponent() ->OnRequestFinished.AddLambda( [](FAIRequestID RequestID, const FPathFollowingResult& Result) { if (Result.IsSuccess()) { // 도착 } });

SetAllowPartialPath(true)로 설정하면 목적지까지 완전한 경로가 없어도 가능한 만큼 이동합니다. 도달할 수 없는 위치로의 이동 요청이 즉시 실패하는 것을 방지합니다.

04

NavMesh 디버깅과 시각화

NavMesh 문제 진단 도구

NavMesh 관련 문제는 시각화 도구를 통해 진단합니다. 에디터의 Show 옵션과 콘솔 명령어로 NavMesh 상태, 경로, 문제 영역을 확인할 수 있습니다.

설정// NavMesh 시각화 // 뷰포트: Show → Navigation // 녹색: 이동 가능 영역 // 빨간 경계: NavMesh 엣지 // 파란 경계: 타일 경계 // 콘솔 명령어 // ShowFlag.Navigation 1 NavMesh 표시 // ai.debug.nav 1 Navigation 디버그 // p.navmesh.draw 1 상세 NavMesh 렌더링 // 문제 진단 체크리스트: // 1. NavMeshBoundsVolume이 영역을 감싸고 있는가? // 2. Agent Radius/Height가 Pawn 크기와 일치하는가? // 3. Max Slope이 경사면 각도보다 큰가? // 4. Max Step Height이 계단 높이보다 큰가? // 5. Geometry가 올바른 Collision 채널을 사용하는가? // Navigation Invoker (동적 로딩) // 오픈 월드에서 전체 NavMesh 대신 // AI 주변만 동적으로 NavMesh 생성 // Project Settings → Navigation System // → bUseNavigationInvokers: true // Navigation Invoker 컴포넌트 UNavigationInvokerComponent* NavInvoker = CreateDefaultSubobject<UNavigationInvokerComponent>( TEXT("NavInvoker")); NavInvoker->SetGenerationRadii(5000.f, 7000.f); // TileGenerationRadius: 생성 범위 // TileRemovalRadius: 제거 범위
핵심

오픈 월드에서는 Navigation Invoker를 사용하여 AI 주변만 NavMesh를 동적 생성하세요. 전체 맵의 NavMesh를 한 번에 빌드하면 수 GB의 메모리가 필요할 수 있습니다.

SUMMARY

핵심 요약

  • RecastNavMesh는 Voxelization 기반으로 NavMesh를 생성하며, Cell Size가 정밀도를 결정한다
  • Agent Radius/Height/MaxSlope/MaxStepHeight가 NavMesh 생성의 핵심 파라미터이다
  • 다중 Agent 설정 시 메모리가 Agent 수에 비례하므로 비슷한 크기의 Agent는 통합해야 한다
  • 오픈 월드에서는 Navigation Invoker로 AI 주변만 동적 NavMesh를 생성하여 메모리를 절약한다
PRACTICE

도전 과제

배운 내용을 직접 실습해보세요

실습 1: NavMesh 기본 설정

레벨에 NavMeshBoundsVolume을 배치하고 Agent Radius, Agent Height를 프로젝트의 캐릭터 크기에 맞게 설정하세요. P 키로 NavMesh를 시각화하고 이동 불가 영역이 올바르게 차단되는지 확인합니다.

실습 2: NavMesh 디버깅

RecastNavMesh의 Draw Offset을 조정하여 NavMesh를 명확히 시각화하세요. 계단, 경사로, 좁은 통로에서 Agent가 올바르게 이동하는지 테스트하고 Cell Size/Height를 튜닝합니다.

심화 과제

다른 크기의 AI(소형 드론, 대형 몬스터)를 위해 여러 Agent 타입의 NavMesh를 동시에 생성하세요. 각 에이전트가 자신의 NavMesh를 사용하여 이동하도록 AIController에서 PreferredNavData를 설정합니다.