본문 바로가기

프로그래밍/Unity

Unity AI Navigation

이번 시간에는 AI Navigation에 대해 알아보겠다.

 

 

 

 

1. AI Navigation

NaveMesh를 이용한 agent 이동

https://docs.unity3d.com/Packages/com.unity.ai.navigation@2.0/manual/index.html

 

Unity AI Navigation document를 보면 다음과 같이 설명 되어 있다.

 

내비게이션 시스템을 사용하면 게임 세계를 지능적으로 이동할 수 있는 캐릭터를 만들 수 있습니다. 이러한 캐릭터는  지오메트리에서 자동으로 생성되는 내비게이션 메시를 사용합니다. 동적 장애물을 사용하면 런타임에 캐릭터의 내비게이션을 변경할 수 있으며, 내비게이션 메시 링크를 사용하면 문을 열거나 틈새를 뛰어넘거나 난간에서 뛰어내리는 등의 특정 동작을 구현할 수 있습니다.

 

NavMesh를 이용하여 AI가 이동 할 수 있는 영역을 지정하여 그 영역 안에서 다양하게 활동하게 해주는 기능인 것 같다.

우리는 이를 통해 적 몬스터가 주변을 Patrol하는 기능을 간단하게 구현할 수 있다.

 

 

경로 찾기

 

경로를 찾는 방법은 A* 알고리즘을 사용한다고 한다. A* 알고리즘은 출발 노드에서 목표 노드까지 최단 경로를 찾는 그래프 탐색 알고리즘이다.

 

 

 

2. Unity 활용

 

 

 

Unity->PackageManager에서 설치할 수 있으며 Window 창에 AI가 뜬 것을 확인 할 수 있다.

 

 

Navigation을 열게 되면 다음과 같이 4가지 창을 볼 수 있는데 기능은 다음과 같다.

 

Agents AI 캐릭터에게 붙이는 이동 컴포넌트.
Areas AI가 어떤 지역을 어떻게 인식/이동하는지를 결정하는 네비게이션 영역 타입.
Bake 씬 안의 지형(바닥/벽)을 분석해서 NavMesh(걸을 수 있는 영역)를 생성하는 작업.
Object NavMesh를 만들 때 영향을 주는 네비게이션 오브젝트들.

 

위 정보들로 우리가 만든 지형(Terrian)에 Bake하여 NavMesh를 생성하여 AI가 이동하는 영역을 지정할 수 있다.

 

 

 

3. NaveMesh.SamplePosition

public class AIMove : MonoBehaviour
{
    private NavMeshAgent agent;
    public LayerMask raycastMask; // 바닥 레이어 등

    void Start()
    {
        agent = GetComponent<NavMeshAgent>();
        
        InvokeRepeating("Move", 0.3f);
    }
    
    public Move()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        if (Physics.Raycast(ray, out RaycastHit hit, 100f, raycastMask))
        {
            // SamplePosition을 이용해 NavMesh 위의 실제 가능한 위치 찾기
            if (NavMesh.SamplePosition(hit.point, out NavMeshHit navHit, 1.0f, NavMesh.AllAreas))
            {
                agent.SetDestination(navHit.position);
            }
        }
    }
}

 

NavMesh의 SamplePosition을 통해 장애물을 피해 가능한 위치를 찾고 agent의 SetDestination을 사용하여 이동 시킬 수 있다.

 

 

public static bool SamplePosition(Vector3 sourcePosition, out AI.NavMeshHit hit, float maxDistance, int areaMask);

 

sourcePosition 샘플 쿼리의 출처.
hit 결과 위치의 속성을 저장합니다. 값은 hit.normal계산되지 않습니다. 항상 (0,0,0)입니다
maxDistance sourcePosition으로부터 이 거리 내에 있는 샘플을 샘플링합니다.
areaMask 가장 가까운 지점을 찾을 때 허용되는 NavMesh 영역을 지정하는 마스크입니다.

 

 

public bool SetDestination(Vector3 target);

 

target 탐색할 대상 지점입니다.