내비메시(NavMesh)는 게임 월드에서 걸을 수 있는 표면을 뜻한다. 내비 메시를 사용하여 게임 월드 안에 움직일 수 있는 한 위치에서 다른 위치로 이동할 수 있는 경로를 찾을 수 있다.
내비메시 에이전트(NavMesh Agent) 컴포넌트를 사용하여 각자의 목적지로 이동하는 동안 서로를 피할 수 있는 캐릭터를 생성할 수 있다. 외에도 장애물 또한 피하는 방법을 알 수 있다.
오프 메시 링크(Off-Mesh Link) 컴포넌트를 사용하여 걸을 수 있는 표면만으로 정의할 수 없는 울타리 같은 뛰어넘거나, 문을 지나기 전에 문을 여는 행동 등 모두 오프 메시 링크를 통해 정의할 수 있다.
네비메시 장애물(NavMesh Obstacle) 컴포넌트를 사용하여 에이전트가 월드를 탐색하는 동안 회피해야 하는 움직이는 장애물을 정의할 수 있다.
2가지 문제를 해결해야 한다.
1. 목적지를 찾기 위해 필요한 추론
2. 목적지까지 이동한느 방법
게임 씬에서 걸을 수 있는 영역을 나타내기 위해서 내비게이션 시스템은 자체적인 데이터를 갖는다. Unity에서는 에이전트는 실런더로 정의되고, 걸을 수 있는 영역은 씬의 지오메트리에서 에이전트가 설 수 있는 위치를 테스트하여 자동으로 필드 되고, 이러한 위치가 씬 지오메트리의 맨 우ㅟ에 위치한 표면에 연결된다.
시작 위치와 목적지 위치를 가장 가까운 폴리곤에 매핑한다. 이동하며 방문한 모든 폴리곤의 경로를 추적하여 목적지까지 연결해주는 폴리곤의 순서를 찾을 수 있다. 이렇게 경로를 찾는 일반적인 알고리즘은 A*이며, Unity에서는 이를 사용한다.
위에서 찾은 경로로 이동하며 가장 가까운 통로를 따라 움직이는 방법으로 목적지를 달성한다. 하지만 여러 에이전트가 동시에 움직인다면 충돌을 피하기 위해 원래 경로를 이동 경로를 이탈할 수 있다.
목적지에 도달하기 위한 원하는 방향과 속도를 계산하고 다른 에이전트와 충돌이 발생하는 것을 파악하고, 충돌하지 않게 적절한 균형점을 찾아 새로운 속도를 선택한다.
장애물 회피가 적용된 이후에 최종 속도가 계산되어 자연적이고 부드러운 움직임을 위치 가속도까지 계산된다.
내비메시 폴리곤 사이의 연결을 탐색 시스템 내부의 링크를 통해서 정의해서 링크 지점에서 특정한 액션이 이루어진다.
내비메시 생성과정을 내비메시 베이킹이라고 부른다.
유니티에서 내비메시 생성은 Navigation 창(Window->AI->Navigation)에서 이루어진다.
물체 선택 후 Navigation static을 누르면 장애물로 인식한다.
네비게이션 창이 아니라 Inspector 창에서도 설정이 가능하다.
Navigation 창에서 Bake 탭에서 이동 가능 기울기, 높이 등을 정한 후 Bake 버튼을 누르면 아래와 같이
네비메시 설정이 되고, NavMesh라는 베이킹 된 파일이 생긴다.
// MoveTo.cs
using UnityEngine;
using UnityEngine.AI;
public class MoveTo : MonoBehaviour {
public Transform goal;
void Start () {
NavMeshAgent agent = GetComponent<NavMeshAgent>();
agent.destination = goal.position;
}
}
Navigation Agent를 이용해서 목표 지점까지 이동하는 스크립트이다.
다음과 같이 컴포넌트를 줘가지고 Navigation Obstacle을 만들 수 있다.
마지막으로 에이전트가 장애물을 피하여 경로를 찾을 수 있도록 내비메시 장애물(NavMesh Obstacle) 인스펙터에서 Carve 설정을 활성해야 한다.
Carve를 설정해야지 NavMesh에서 제외한다.
네비게이션 컴포넌트 관련해서는 다음 DOCS에서 확인할 수 있다.
내비메시 에이전트
https://docs.unity3d.com/kr/2019.4/Manual/class-NavMeshAgent.html
내비메시 장애물
https://docs.unity3d.com/kr/2019.4/Manual/class-NavMeshObstacle.html
오프 메시 링크
https://docs.unity3d.com/kr/2019.4/Manual/class-OffMeshLink.html