Unity NavMeshAgent

용준·2023년 8월 15일
0

Unity

목록 보기
4/19
  • NavMesh는 유니티에서 제공하는 네비게이션 기능입니다.
  • 목표를 향해 움직일 때 서로를 피해가는 캐릭터 생성에 유용합니다.

NavMesh 생성

가장 먼저 네비게이션 기능(NavMesh)을 활성화 할 맵 오브젝트를 선택합니다.
인스펙터 창의 우측 상단에 Static 설정에서 Navigation Static을 체크합니다.
Navigation에서 Bake를 합니다. (Window 메뉴 → AI → Navigation)
Bake가 다되면 파란색 영역이 생성됩니다. 이 영역은 캐릭터가 길을 찾아서 이동할 수 있는 NavMesh입니다.


플레이어 추적 스크립트

  • NavMesh의 함수와 프로퍼티를 이용하기 위해 UnityEngine.AI 네임스페이스를 선언합니다.

코드 초안

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class Enemy : MonoBehaviour
{
    NavMeshAgent nav;
    public GameObject player;
    
    void Start()
    {
        nav = GetComponent<NavMeshAgent>();
    }
    
    void Update()
    {
        nav.SetDestination(player.transform.position);
        transform.LookAt(player.transform.position);
    }
}
  • SetDestination(target) 함수는 target을 향해 추적합니다.
  • transform.LookAt(target) 함수는 해당 오브젝트가 target을 바라봅니다.

Enemy가 Player를 쫓아오지만 Player가 멈추게 되어도 부딪혀 밀어 버리는 현상이 생깁니다. 그러기 위해서 코드를 수정할 필요가 있습니다.


코드 수정본

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class Enemy : MonoBehaviour
{
    NavMeshAgent nav;
    public GameObject player;
    float dist;

    void Start()
    {
        nav = GetComponent<NavMeshAgent>();
    }

    void Update()
    {
        nav.SetDestination(player.transform.position);
        transform.LookAt(player.transform.position);
        dist = Vector3.Distance(player.transform.position, transform.position);
        UpdateStop();
    }

    void UpdateStop()
    {
        if (dist < 10f) nav.isStopped = true;
        if (dist > 10f) nav.isStopped = false;
    }
}

dist 변수를 추가했습니다. dist는 Vector3.Distance 함수를 이용해 Player와 Enemy 사이의 거리를 계산한 값을 실시간으로 저장합니다.

  • 오브젝트 간 거리를 계산하는 방법은 Distance 외에도 몇가지 있습니다.
    1) Vector3.Distance
    2) Vector3.magnitude
    3) Vector3.sqrMagnitude

Distance와 magnitude는 정확한 거리 계산을 하기 때문에 거리를 알고 싶을 때 사용합니다.
sqrMagnitude는 거리의 제곱 값을 리턴하는데 특정 거리보다 작거나 큰지 비교만 하고 싶을때 사용합니다.


Ray 추가

스크립트에서 오브젝트의 거리가 10f보다 가까워지면 멈추고, 10f보다 멀어지면 쫓아오게 됩니다.
10f가 어느정도 길이인지 어림짐작 할 수는 있지만 정확하게 알 수는 없습니다. 만약 10f가 아니라 훨씬 크거나 작은 세밀한 값일 경우에는 훨씬 더 어렵습니다.
그렇기 때문에 개발자는 Scene 뷰에서 거리를 확인할 수 있게 기즈모를 추가해주는 것이 좋을 것 같습니다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class Enemy : MonoBehaviour
{
    NavMeshAgent nav;
    public GameObject player;
    float dist;
    Ray ray;

    void Start()
    {
        nav = GetComponent<NavMeshAgent>();
    }

    void Update()
    {
        nav.SetDestination(player.transform.position);
        transform.LookAt(player.transform.position);
        dist = Vector3.Distance(player.transform.position, transform.position);
        UpdateStop();
    }

    void UpdateStop()
    {
        if (dist < 10f) nav.isStopped = true;
        if (dist > 10f) nav.isStopped = false;
    }

    private void OnDrawGizmos()
    {
        ray.origin = transform.position;
        ray.direction = transform.forward;
        Debug.DrawRay(ray.origin, ray.direction * 10f, Color.red);
    }
}

  • OnDrawGizmos 함수에 사용하는 Gizmo는 매 프레임마다 호출되어 항상 노출됩니다.

  • RaycastHit는 Ray에 의한 충돌 체크입니다. 만약 충돌 체크가 아니라 단순히 Ray만 쏘고 싶다면 메소드 상단에서 ray 변수를 생성한 뒤 OnDrawGizmos 함수에서는 발사지점, 발사방향, 색상만 지정해주는 것으로 쉽게 만들 수 있습니다.


Ray 대신 다른 방법

Gizmos 클래스를 이용한다면 직선 Ray 외에도 다양한 레퍼토리가 가능합니다.

FunctionExplain
color색상을 변경합니다.
DrawCube큐브를 생성합니다.
DrawGUITexture
DrawIcon
DrawLine
DrawMesh
DrawRay
DrawSphere
DrawWireCube
DrawWireMesh
DrawWireSphere
private void OnDrawGizmos()
{
	ray.origin = transform.position;
	Gizmos.color = Color.red; //color를 지정하지 않을 시 기본색상(흰색)
	Gizmos.DrawWireSphere(ray.origin, 10f);
}

각 함수의 파라미터에는 발사지점과 길이만 추가하면 됩니다.

아래는 DrawWireSphere 함수를 사용한 기즈모입니다.


프로퍼티

프로퍼티설명
Base OffsetNavMeshAgent Y축 방향 위치
Speed최대 이동 속도
Augular Speed최대 회전 속도
Acceleration최대 가속
Stopping Distance목표 위치로부터 설정한 거리만큼 떨어져 정지하는 기능입니다.
Auto Braking활성화 시 에이전트는 목적지에 다다를 때 속도를 줄입니다. 멀티플 포인트 사이에서 부드럽게 움직여야 하는 순찰과 같은 동작을 할 때에는 반드시 비활성화 시켜야 합니다.
RadiusAgent의 장애물과 에이전트 간의 충돌을 계산하는 반경입니다.
HeightAgent가 장애물 밑으로 지나갈 수 있는 높이 간격입니다.
Quality장애물 회피 품질입니다. 에이전트의 수가 많다면 장애물 회피 품질을 줄임으로써 CPU 시간을 절약할 수 있습니다. 회피를 없음으로 설정할 경우 충돌만 해결할 수 있을 뿐 다른 에이전트와 장애물에 대한 적극적인 회피는 하지 않습니다.
Priority낮은 우선 순위의 에이전트는 이 에이전트의 회피 대상에서 제외됩니다. 값은 0에서 99사이에서 설정되어야 하며 낮은 숫자가 높은 우선 순위임을 의미합니다.
Auto Traverse Off Mesh자동적으로 횡단하려면 True로 설정해야하고, 애니메이션을 사용하거나 오프메시 링크를 횡단하는 특정한 방법을 사용하고 싶다면 이를 False로 설정합니다.
Auto Repath활성화 시 경로 일부분의 끝에 도달하면 경로를 재탐색합니다. 목적지까지 경로가 없다면 목적지에서 제일 가깝게 도달할 수 있는 위치까지 부분적인 경로가 생성됩니다.
Area Mask경로 탐색에 어떠한 영역 타입을 고려할 것인지를 설명합니다. NavMesh Baking을 위해 Mesh를 준비할 때 각각의 Mesh 영역 타입을 설정할 수 있습니다. 예를 들어 계단을 특별한 영역 타입으로 표시하고 몇몇 캐릭터 타입의 계단 이용을 금지할 수 있습니다.

0개의 댓글