내일배움캠프 8주차 1일차 TIL - AI 내비게이터

백흰범·2024년 6월 4일
0
post-thumbnail

오늘 한 일

  • 팀 프로젝트 기획 후 진행
  • AI 내비게이터 배우기


AI 내비게이터

개념

유니티의 기능 AI 길찾기 기능 중 하나로 런타임 이전에 이동 가능한 영역을 지정하고, Nav Mesh Agent 컴포넌트를 활용하여 해당 AI에게 길찾기 능력을 부여해주는 기능이다.

특징

  • 3D 공간을 그리드로 나누어 이동 가능한 영역과 불가능한 영역을 구분하는 매쉬입니다.
    캐릭터는 이 영역을 기반으로 경로를 계산해서 이동합니다.
    • 하나는 움직이지 않는 지형을 위한 영역 지정이고 또 다른 하나는 움직이는 오브젝트를 위한 영역 지정이다.

Pathfinding(경로 탐색)

  • 캐릭터의 현재 위치에서 목표 지점까지 가장 적절한 경로를 찾는 알고리즘입니다.
  • 주로 A* 알고리즘 등이 사용되며, 지정된 목표 위치까지 최단 경로를 탐색합니다.

Steering Behavior (스티어링 동작)

  • 캐릭터나 NPC가 경로를 따라 이동할 때보다 자연스러운 동작을 구현하는데 사용됩니다.
  • 동적으로 캐릭터의 이동 방향과 속력을 조정하여 부드럽고 현실적인 이동을 시뮬레이션 합니다.

Obstacle Avoidance (장애물 피하기)

  • 캐릭터가 이동 중에 장애물과 충돌하지 않도록 하는 기술입니다.
    각종 센서나 알고리즘을 사용하여 장애물을 감지하고 피하는 동작을 수행합니다.

Local Avoidance (근접 회피)

  • 여러 캐릭터나 NPC가 서로 충돌하지 않도록 하는 기술입니다.
    캐릭터들 사이의 거리를 유지하거나 회피 동작을 수행하여 서로 부딪히지 않도록 합니다.

사용하는 방법

1. 내비게이션 (Obsolete)

들어가기 전에 기초 설명

Agents

  • 길 찾기를 수행할 Agent들의 Obstacle Avoidance를 설정하고 모으는 리스트이다.

Areas

  • 각 영역의 가중치 값을 정하는데 사용하는 항목이다.

Bake

  • 모든 기초 설정이 완료되었다면, Bake를 하여 Agents들의 이동 영역을 산출해준다.

Object

  • 선택한 오브젝트들에게 Area를 부여해주는 곳이다
  • Navigation Static을 선택해주지 않으면, 해당 오브젝트에게서 이동 영역을 산출해줄 수 없다.


이동 가능 영역 Bake하기

  • 내비게이션(Obsolete) 창 열기

  • Object를 선택하고 Inspector창에 있는 Navigation (Obsolete) 창을 선택한다.

  • Bake를 하기 전에 Static을 활성화하고, 원하는 Area를 설정한다.

  • 산출하고자 하는 오브젝트들에게 Object 설정을 해줬다면 Bake를 해주자
  • 필자는 이동영역이 붕뜨는 것을 방지하기 위해서 Radius를 0.1로 설정하고 Bake한다.

  • 아래와 같이 보이긴한데 흐릿하게 보인다면 잘 산출된 것이다.


이제 이동 영역을 정했으니 이동 영역을 사용하는 동물을 만들어보자


  • AI Navigation을 활용한 캐릭터의 이동을 위해서는 들어가야하는 컴포넌트로 오브젝트의 자연스러운 이동이나 장애물 피하기 경로 찾기 설정들을 할 수 있다.
  • 원하는 오브젝트에다가 위 컴포넌트를 추가시키자!

각종 설정

Steering

  • Speed 최대 이동 속도(초당 월드 단위로)
  • Angular Speed 최대 회전 속도(초당 각도)
  • Acceleration 최대 가속(제곱 초당 월드 단위로)
  • Stopping distance 에이전트는 목표 위치에 가까워졌을 시 정지합니다.
  • Auto Braking 활성화 시 에이전트는 목적지에 다다를 때 속도를 줄입니다.
    에이전트가 멀티플 포인트 사이에서 부드럽게 움직여야 하는 순찰과 같은 동작을 할 때에는 반드시 비활성화 시켜야 합니다.

Obstacle Avoidance

Radius 에이전트의 반경은 장애물과 다른 에이전트 간의 충돌 계산하기 위해 사용됩니다.
Height 에이전트가 장애물 밑으로 지나갈 수 있는 높이 간격입니다.
Quality 장애물 회피 품질입니다. 에이전트의 수가 많다면 장애물 회피 품질을 줄임으로써 CPU 시간을 절약할 수 있습니다. 회피를 없음으로 설정할 경우 충돌만 해결할 수 있을 뿐 다른 에이전트와 장애물에 대한 적극적인 회피는 하지 않습니다.
Priority 낮은 우선 순위의 에이전트는 이 에이전트의 회피 대상에서 제외됩니다.
값은 0에서 99사이에서 설정되어야 하며 낮은 숫자가 높은 우선 순위임을 의미합니다.


필요한 기초 코드

// 네임스페이스
using UnityEngine.AI; 

// 컴포넌트 가져오기
NavMeshAgent agent;
void Awake()
{
    agent = GetComponent<NavMeshAgent>();
}

기초적으로 사용하게될 각종 NavMeshAgent의 멤버들

프로퍼티

  • isStopped: NavMesh 에이전트가 현재 경로를 따라 이동을 중지하거나 계속하는지를 설정하거나 가져옵니다.
    ( 해당 설정을 활성화 시에는 NavMeshAgent를 이용한 움직임이 정지됩니다.)
  • remainingDistance: 에이전트의 위치와 현재 경로의 목적지 사이의 거리를 나타냅니다.

메서드

  • bool SamplePosition(Vector3 sourcePosition, out AI.NavMeshHit hit, float maxDistance, int areaMask)
    (NavMesh) sourcePosition으로부터 지정된 maxDistance 내에서 가장 가까운 NavMesh의 지점을 찾습니다.
  • bool SetDestination(Vector3 target)
    목적지를 설정하거나 업데이트하여 새 경로에 대한 계산을 트리거합니다.

추가적인 설명

  • NavMeshHit
    -> NavMesh 쿼리에 대한 결과 정보가 담겨져있다.
    프로퍼티 : distance, hit, mask, normal, position

배회하는 코드

    void Update()
    {
        // 플레이어 감지
        playerDistance = (transform.position - CharacterManager.Instance.Player.transform.position).sqrMagnitude; // sqr을 활용했으니 제곱하는 걸 잊지 맙시다.

        WanderingState();
    }

    void WanderingState()
    {
        if (agent.remainingDistance < 0.1f)
        {
            NewWanderingPoint();
        }
    }

    private void NewWanderingPoint()
    {
        NavMesh.SamplePosition(transform.position + (Random.onUnitSphere * detectDistance), out NavMeshHit hit, detectDistance, NavMesh.AllAreas);
        agent.SetDestination(hit.position);
    }
  • 위 코드는 목표에 도착하면 주기적으로 목적지를 계속 바꾸는 코드이다.

적용 결과

  • 자신의 주위로 계속해서 배회한다. (detectDistance를 1로 설정해두었다.)


각종 코드 주의 사항

  • SetDestination을 사용할 때 곧바로 Vector3를 넣으면 의도된대로 작동이 안될 수도 있다.
    -> Navmesh를 벗어난 목적지로 설정해버릴 경우 그대로 자리에서 멈춰버린다.

- SamplePosition은 랜덤으로 정하는 게 아니라 받은 sourceposition값에서 가장 가까운 NavMesh를 찾는 역할을 하는 것이다.

  • SamplePosition은 위와 같은 과정으로 포지션 값을 뽑는 것이고, 만약에 적절한 NavMesh 값을 찾지 못하면 false를 반환한다.


참고 자료

유니티

영상

[유니티] 클릭 이동 구현하기 | Navigation(NavMesh) - 오늘코딩

profile
게임 개발 꿈나무

0개의 댓글