내브메시 컷팅 튜토리얼


내브메시 컷팅은 리캐스트 또는 내브메시 그래프에 의해 생성된 기존 내브메시에 구멍을 뚫는 데 사용됩니다. 리캐스트/내브메시 그래프는 일반적으로 기존 노드의 매개변수만 변경하거나(예: 삼각형 전체를 이동 불가능하게 만듦) 전체 타일을 다시 계산하는 것을 허용하는데, 이는 유연성이 떨어지거나 매우 느립니다. 내브메시 컷팅을 사용하면 RTS 게임의 새로운 건물과 같은 장애물로 인해 차단된 내브메시의 일부를 제거(컷)할 수 있지만, 내브메시에 새로운 것을 추가하거나 노드의 위치를 변경할 수는 없습니다. 이는 리캐스트 그래프에서 전체 타일을 처음부터 다시 계산하는 것보다 훨씬 빠릅니다.

 

NavmeshCut 컴포넌트는 2D 모양을 사용하여 내브메시를 컷팅합니다. 이 모양은 내장된 2D 모양(사각형/원) 중 하나 또는 3D 모양(큐브/구/캡슐) 중 하나로 생성될 수 있으며, 컷팅 시 2D 모양으로 투영됩니다. 또한 컷으로 사용할 사용자 지정 2D 메시를 지정할 수도 있습니다.


사각형/원 모양은 3D가 아니라는 점에 유의하십시오. 이를 회전하면 2D 모양이 회전한 후 XZ 평면에 투영됩니다. 따라서 대부분의 경우 3D 모양(큐브/구/캡슐)을 사용하는 것이 더 쉽기 때문에 이를 사용하는 것이 좋습니다.

씬 뷰에서  NavmeshCut 은 돌출된 2D 모양처럼 보입니다. 이는 내브메시 컷이 높이를 가지기 때문입니다. 컷팅은 내브메시와 닿는 부분만 자릅니다. 성능상의 이유로 내브메시의 삼각형의 바운딩 박스만 확인하므로, 돌출된 모양과 교차하지 않더라도 바운딩 박스와 교차하는 삼각형을 자를 수 있습니다. 그러나 대부분의 경우 이는 큰 차이를 만들지 않습니다.

또한 isDual 필드를 `true`로 설정하여 내브메시 컷을 듀얼 모드로 설정할 수 있습니다. 이는 내브메시에 구멍을 내는 대신 경계선을 따라 내브메시를 분할하지만 내부와 외부를 모두 유지합니다. 이는 예를 들어 내브메시 삼각형과 정확하게 일치하지 않는 영역의 패널티를 변경하려는 경우에 유용할 수 있습니다. 이는 종종 GraphUpdateScene 컴포넌트와 결합하여 사용됩니다(그러나 GraphUpdateScene 컴포넌트는 그래프가 다시 업데이트되면 자동으로 패널티를 재적용하지 않습니다).

기본적으로 내브메시 컷은 회전 또는 스케일링을 고려하지 않습니다. 이를 고려하려면 useRotationAndScale 필드를 `true`로 설정할 수 있습니다.

Custom meshes
대부분의 경우 내장된 모양을 사용할 수 있지만, 경우에 따라 사용자 지정 컷팅 메시가 유용할 수 있습니다. 사용자 지정 메시는 아래 그림과 같이 평평한 2D 모양이어야 합니다. 스크립트는 해당 메쉬의 윤곽을 찾아 그 모양을 컷으로 사용합니다. 모든 노멀을 부드럽게 하고 메시에 UV 정보가 포함되지 않도록 하십시오. 그렇지 않으면 Unity가 버텍스를 분할하여 스크립트가 올바른 윤곽을 찾지 못할 수 있습니다. 매우 고다각형 메쉬는 사용하지 않는 것이 좋습니다. 이는 내브메시 그래프에 많은 노드를 생성하여 경로 찾기 속도를 저하시킬 수 있습니다. 매우 고다각형 메쉬는 많은 얇은 삼각형을 추가하여 최적이 아닌 경로를 생성할 수도 있습니다.

 


Update frequency
내브메시 컷은 일반적으로 매우 빠르기 때문에 자주 내브메시를 업데이트하고 싶을 수 있습니다(예: 몇 프레임마다 한 번씩). 그러나 너무 자주 업데이트하면 그래프에서 경로를 따르는 에이전트에 영향을 미칠 수 있습니다.

내브메시 컷이 에이전트 근처에서 그래프를 업데이트하면 일반적으로 경로를 다시 계산해야 합니다. 이것이 너무 자주 발생하면 경로 찾기 작업 스레드가 경로 찾기 요청으로 과부하되어 개별 경로 찾기 요청의 대기 시간이 길어질 수 있습니다. 이는 에이전트의 반응성을 떨어뜨릴 수 있습니다.

따라서 업데이트 빈도를 적절히 유지하는 것이 좋습니다. 플레이어는 내브메시가 초당 20번 업데이트되는 것과 초당 2번(또는 그보다 적게) 업데이트되는 것을 눈치채지 못할 것입니다.

이는 주로 updateDistance updateRotationDistance 필드를 사용하여 제어할 수 있습니다. 그러나 업데이트의 전역 빈도를 제어할 수도 있습니다. 이는 다음 섹션에서 설명합니다.

Control updates through code
내브메시 컷은 주기적으로 적용되지만, 때로는 그래프가 최신 상태인지 즉시 확인하고 싶을 수 있습니다. 그런 경우 다음 코드를 사용할 수 있습니다.

```csharp
AstarPath.active.FlushGraphUpdates();
```

// 경로 찾기 스레드가 현재 수행 중인 작업을 완료하는 대로 예약된 업데이트를 실행하도록 설정합니다.
AstarPath.active.navmeshUpdates.ForceUpdate();
// 업데이트가 완료될 때까지 차단합니다.
AstarPath.active.FlushGraphUpdates();

스크립트가 내브메시 컷이 변경되었는지 확인하는 빈도를 제어할 수도 있습니다. 컷이 매우 많은 경우 성능을 위해 확인 빈도를 줄이는 것이 좋을 수 있습니다.

// 매 프레임마다 확인 (기본값)
AstarPath.active.navmeshUpdates.updateInterval = 0;

// 0.1초마다 확인
AstarPath.active.navmeshUpdates.updateInterval = 0.1f;

// 변경 사항을 절대 확인하지 않음
AstarPath.active.navmeshUpdates.updateInterval = -1;
// 업데이트를 수동으로 예약해야 합니다.
AstarPath.active.navmeshUpdates.ForceUpdate();

이 설정은  AstarPath 인스펙터의 설정(Settings) 아래에서도 찾을 수 있습니다.


Navmesh cutting and tags/penalties
내브메시 컷은 그래프가 처음 스캔될 때 또는 리캐스트 그래프 타일이 처음부터 다시 계산될 때 발생하는 업데이트에 대해서만 태그를 보존할 수 있습니다.

이것은 GraphUpdateScene 컴포넌트를 사용하여 동적으로 적용한 태그가 내브메시 컷이 적용될 때 손실될 수 있음을 의미합니다. 따라서 태그와 내브메시 컷팅을 결합해야 하는 경우,  RecastMeshObj 포넌트를 사용하여 태그를 적용하는 것이 좋습니다. 이 방법은 내브메시 컷팅과 원활하게 작동합니다.

내부적으로는 그래프가 스캔될 때 내브메시 컷팅 서브시스템이 그래프의 모든 삼각형과 태그의 스냅샷을 찍습니다. 그런 다음 컷팅이 발생할 때마다 이 데이터를 참조하여 컷팅이 끝난 후 새로운 삼각형에 스냅샷의 태그가 복사됩니다.

컷팅이 끝난 후 그래프 업데이트를 사용하여 태그와 패널티를 적용할 수도 있습니다. 예를 들어, 내브메시 컷을 서브클래싱하고  UsedForCut 메서드를 오버라이딩하여 적용할 수 있습니다. 그러나 앞서 언급한  RecastMeshObj 를 사용하는 것이 더 견고한 솔루션이므로 권장됩니다.

 A* Pro 기능
이 기능은 A* Pathfinding Project Pro 기능입니다. 이 기능/클래스/변수는 A* Pathfinding Project의 무료 버전에는 존재하지 않거나 기능이 제한될 수 있습니다.
Pro 버전은 여기에서 구매할 수 있습니다.
http://www.arongranberg.com/2013/08/navmesh-cutting/ 참조

 

'유니티 에셋 > A* Pathfinding project pro' 카테고리의 다른 글

Saving and Loading Graphs  (0) 2024.05.27
Working with tags  (0) 2024.05.27
Using nodes  (0) 2024.05.27
Grid Graph Rules > Writing Custom Grid Graph Rules  (0) 2024.05.26
Grid Graph Rules  (0) 2024.05.26

+ Recent posts