샘플용 프로젝트 생성
언리얼 엔진 공식문서 - 커스텀 내비게이션 영역 및 쿼리 필터
https://dev.epicgames.com/documentation/ko-kr/unreal-engine/custom-navigation-areas-and-query-filters-in-unreal-engine?application_version=5.5
- 언리얼 엔진의 내비게이션 시스템은 AI가 내비게이션 메시를 사용하여 레벨 내에서 경로를 찾고 이동하도록 지원
- 이때 내비게이션 메시 내에서 각 내비게이션 폴리곤의 비용을 비교하여 목적지에 도달하는 최적의 경로를 결정(A* 알고리즘). 경로상의 모든 폴리곤이 같은 비용이면 타깃까지의 최단 경로를 선택함.
- 내비게이션 모디파이어 볼륨 및 내비게이션 쿼리 필터를 사용하여 내비게이션 폴리곤 비용에 영향을 줄 수 있음
내비게이션 모디파이어 볼륨
- 영역 클래스를 사용하여 볼륨 내 내비게이션의 디폴트 비용 배수를 결정
- 영역 클래스로 AI가 영역에 들어갈 때 적용되는 초기 비용인 고정된 영역 진입 비용(Fixed Area Entering Cost) 을 정의할 수도 있음
- 영역 클래스는 AI가 레벨에서 이동하는 방식에 영향을 주기 위해 필요한 만큼 얼마든지 생성 가능
- 내비게이션 모디파이어 볼륨의 기본적인 기능은 이전에 정리해놓음
-> AI_NavMesh
영역 클래스의 디폴트 비용
- 3개의 내비게이션 모디파이어 볼륨을 두고, 3개의 NavArea를 상속받은 클래스를 생성
- 각각 DrawColor를 두고, 영역을 구분함

- 2개의 NavArea의 Default Cost를 4.0으로 증가 -> 돌아서 가게 됨
- 내부 알고리즘으로 계산을 하기 때문에 2.0으로 증가시키면 아래처럼 움직이지는 않음


영역 클래스의 Fixed Area Entering Cost
- Area에 진입할 때 한 번만 추가되는 비용
- A* 알고리즘에서는 각 폴리곤 사이를 이동할 때, 거리에 따라 비용이 누적됨. 그 때, 특정 Area에 들어갈 때 추가로 고정 비용을 붙이고 싶은 경우에 사용
- 간단한 계산 수식 :
Cost = Travel Distance * Travel Cost + Fixed Area Entering Cost

- 가운데의 Area에 Fixed Area Entering Cost를 1000.0으로 증가 -> 돌아서 가게 됨
- 정확한 수치는 계산하기 어려운 것으로 보이고, 해당 경우에 500.0까지는 가운데의 Area로 가게 됨

내비게이션 쿼리 필터
- 하나 이상의 영역 클래스에 대한 정보를 포함하며, 비용 값을 오버라이드할 수 있음
- 쿼리 필터는 AI가 레벨에서 이동하는 방식을 더 자세히 커스터마이징할 수 있음
사용법
- Navigation Query Filter 클래스를 상속받아서 영역 클래스에 대한 정보를 받아서 사용

- 캐릭터의 Filter Class에서 적용하고자 하는 Navigation Query Filter를 선택


- c++에서는 AIController ->
MoveTo() 함수에서 FilterClass 설정 혹은 UNavigationSystemV1에서 직접 사용할 수도 있음 (이동 시에만 쿼리 적용)
/** MoveTo() 함수에서 FilterClass 설정 **/
FAIMoveRequest MoveReq;
MoveReq.SetGoalLocation(Destination);
MoveReq.SetAcceptanceRadius(50.0f);
// 필터 클래스 지정
MoveReq.SetNavigationFilter(*MyFilterClass);
// 실행
FNavPathSharedPtr NavPath;
GetController()->MoveTo(MoveReq, &NavPath);
/** UNavigationSystemV1 **/
UNavigationSystemV1* NavSys = UNavigationSystemV1::GetCurrent(GetWorld());
if (NavSys && MyFilterClass)
{
FPathFindingQuery Query;
NavSys->BuildPathfindingQuery(
*MyController,
*MyController->GetNavAgentProperties(),
StartLocation,
EndLocation,
MyFilterClass,
Query
);
FPathFindingResult Result = NavSys->FindPathSync(Query);
if (Result.IsSuccessful())
{
// 경로 따라가기
}
}