2 minute read

NavMesh Plus

2D용 NavMesh 사용법 정리 원본 깃허브 : NavMesh Plus GitHub Wiki

INTRO

먼저 Unity의 “2D 템플릿”에서 새 프로젝트를 생성합니다. NavMeshPlus를 다운로드하여 NavMeshComponents를 Assets 폴더에 복사합니다. 이제 씬에서 마우스 오른쪽 버튼을 클릭하고 메뉴에서 Create Empty를 선택하여 씬의 루트에 빈 GameObject를 추가합니다. 새 빈 GameObject의 이름을 “NavMesh”로 지정합니다.

  1. 레이아웃 설정:
    • “Layout”이라는 새로운 루트 GameObject를 만들고, 그 아래에 “GameFloor”라는 자식 GameObject를 추가합니다.
    • “GameFloor”에 스프라이트를 드래그 앤 드롭하면 SpriteRenderer 컴포넌트가 자동으로 추가됩니다.
    • “GameFloor”에 NavigationModifier 컴포넌트를 추가하여 탐색 소스로 표시합니다.
  2. NavMeshSurface 추가:
    • “NavMesh” 오브젝트를 선택하고, 인스펙터에서 Add Component를 클릭한 다음 NavigationSurface를 선택합니다.
    • NavigationCollectSources2d 컴포넌트를 추가하고 Surface를 XY로 회전한 후 Bake를 클릭하여 탐색 가능한 평면을 빌드합니다.
  3. 장애물 추가:
    • “Layout”에 “Pond”라는 이름의 오브젝트를 추가하고, 작은 스프라이트를 드롭합니다.
    • NavigationModifier 컴포넌트를 추가하고 Override Area를 체크한 다음 Area Type 필드에서 Not Walkable을 선택합니다.
    • 다시 “NavMesh” 오브젝트에서 Bake를 클릭하여 “Pond”를 탐색 영역에서 제외시킵니다.
  4. NavMeshAgent 설정:
    • NavMeshAgent 컴포넌트를 가진 GameObject를 추가합니다.
    • NavMeshAgent 컴포넌트가 GameObject를 회전시키는 것을 방지하려면 다음 스크립트를 추가합니다:

      void Start()
      {
          var agent = GetComponent<NavMeshAgent>();
          agent.updateRotation = false;
          agent.updateUpAxis = false;
      }
      

GEOMETRY OPTIONS

Unity 2019.3에서 도입된 새로운 API를 사용하면 사용할 지오메트리 소스를 선택할 수 있습니다.

  1. Physics Colliders 사용:
    • 모든 2D 콜라이더를 NavigationModifier와 함께 “Layout” GameObject에 자식으로 배치합니다.
    • Use Geometry 옵션을 Render Meshes에서 Physics Colliders로 변경하고 Bake를 클릭합니다.

TILED

Tilemap 시스템의 일부인 오브젝트를 베이크할 수 있습니다.

  1. Tilemap 설정:
    • 씬에 Tilemap GameObject를 추가합니다.
    • Grid 오브젝트의 자식으로 Tilemap GameObject를 추가하고 각각 “Ground”, “Walls”, “Pond”로 이름을 지정합니다.
    • NavigationModifier를 각 Tilemap에 추가하고 해당 영역을 Walkable 및 Not Walkable로 오버라이드합니다.
    • Bake를 클릭하여 NavMesh를 빌드합니다.

TILE MODIFIER

각 타일이 세계의 속성을 나타내므로, TileSet의 각 타일에 네비게이션 수정자를 할당할 수 있습니다.

  1. NavigationModifierTilemap 사용:
    • NavigationModifierTilemap에 새 요소를 추가하고 자산에서 타일을 선택합니다.
    • 각 타일을 NavigationModifier 위에 오버라이드하거나 기본 상태로 유지합니다.
    • Bake를 클릭하여 단일 TileMap에 레이어가 없는 결과를 얻습니다.

MAZES

미로를 통해 탐색할 수 있도록 설정할 수 있습니다.

  1. 기본 설정:
    • “NavMesh”를 Not Walkable로 설정하고 NavigationModifier 컴포넌트를 Walkable로 설정합니다.
    • Bake를 클릭하여 미로 내에서 탐색할 수 있도록 합니다.

OTHER GRIDS

NavMeshPlus는 육각형, 등각, 다이아몬드형 그리드와 같은 다른 유형의 그리드도 지원합니다.

OVERRIDE BY

타일 맵을 통해 네비게이션할 때는 스프라이트 메쉬를 재정의할 수 있습니다.

  1. 스프라이트 메쉬 재정의:
    • 타일 형태의 메쉬를 가져와 씬에 추가하고, NavMeshCollectSources2d 컴포넌트의 Override By Grid를 체크합니다.
    • Bake를 클릭하여 타일의 메쉬 모양을 사용합니다.

BAKE AT RUNTIME

프로시저 생성된 월드를 가지고 있을 때 런타임에 NavMesh를 빌드할 수 있습니다.

  1. 런타임 베이크:
    • BuildNavMeshAsync 메서드를 호출하여 NavMesh를 빌드합니다.

      public NavMeshSurface Surface2D;
      
      void Start()
      {
          Surface2D.BuildNavMeshAsync();
      }
      
  2. 업데이트:
    • 동적 월드의 경우 UpdateNavMesh를 호출하여 CPU 활용을 절약합니다.

      public NavMeshSurface Surface2D;
      
      void Update()
      { 
          Surface2D.UpdateNavMesh(Surface2D.navMeshData);
      }
      

KNOWN ISSUES

NavMeshAgent 컴포넌트가 Y 축을 따라 이동할 때 멈추거나 설정된 agent.velocity가 작동하지 않는 문제가 있습니다. 이러한 경우를 해결하려면 에이전트의 이동을 조정하는 스크립트를 추가해야 합니다.

static float agentDrift = 0.0001f; // 최소 드리프트 값

void SetDestination(GameObject target)
{   
    if (Mathf.Abs(transform.position.x - target.transform.position.x) < agentDrift)
    {
        var driftPos = target.transform.position + new Vector3(agentDrift, 0f, 0f);
        agent.SetDestination(driftPos);
    }
}