적 캐릭터가 장애물을 피해서 가는 걸 구현한다면 PathFinding같은 알고리즘이 필요하다. 유니티가 3D모델을 분석해 추적할 수 있는  내비게이션 기능을 제공하기 이전 많이 사용되었다. 유니티의 내비게이션 기능을 이용해 주인공을 추적하는 로직을 구현해 보자. 추적을 시작하면 walk애니메이션으로 변경하고 플레이어에 근접했을때 attack 애니메이션으로 변경되도록 메카님을 구성해본다.

네비게이션은 스테이즈를 구성하고 있는 3D메시(지형:Geometry)를 분석해 네비메시(NavMesh) 데이터를 미리 생성하는 방식이다. 추적할 수 있는 영역과 지나갈수 없는 영역을 미리 메시로 만들어 동작을 연출할 수 있다.

 

네비게이션 설정 - Navigation Static Flag

네비게이션을 만들(Bake)려면 그 대상이 무엇인지 지정해야 한다. 우선 바닥으로 사용되는 Floor의 static 옵션을 설정한다.  Floor 인스펙터의 이름 오른쪽의  Static옆 삼각형을 눌러 Navigation Static만 체크한다.

프리팹폴더의 Barrel도 Wall도 Static중 Navigation Static만 체크하고 다이얼로그가 나오면 children까지 변경해준다.

Monster를 선택하고. window>AI>Navigation을 선택하면 Navigation뷰가 나오고 Bake를 누르고 마치면 파란색 영역이 만들어진다. 드럼통 주위는 파란색 메시로 채워지지 않고 구멍이 나있다. 이 영영읍 지나갈 수 없는 영억으로 인식해 추적한 대상이 장애물로 판단한다. Bake는 씬뷰에 플레이전 있는 것들만 인식한다. 동적으로 생성되는 것은 예측할수 없는 것 같다. 따라서 스테이지에 적용된  Barrel 스크립트를 제거한고 프리팹 Barrel을 여기저기 배치하고 Bake를 한번 더 누른다.

플레이어와 몬스터를 떨어트려 놓과 사이에 배치해주기 바란다. 몬스터가 피해가는지

NavMeshAgent 컴포넌트

NavMeshAgent 컴포넌트는 목표를 향해 움직일 때 서로를 피해가는 캐릭터 생성에 유용합니다. 에이전트는 내비메시를 이용하여 게임 월드에 대해 추론하고 서로 또는 기타 움직이는 장애물을 피할 방법을 이해하고 있습니다. 내비메시 에이전트의 스크립팅 API를 이용하여 경로를 찾거나 공간을 추론할 수 있습니다.

 

하이라키에서 Monster를 선택하고 메뉴의 컴포넌트>Navigation>Nav Mesh Agent를 선택한다.

NaveMeshAgent의 각 속성은 다음과 같다.

프로퍼티 기능
에이전트 크기
Radius 에이전트의 반경은 장애물과 다른 에이전트 간의 충돌 계산하기 위해 사용됩니다.
Height 에이전트가 장애물 밑으로 지나갈 있는 높이 간격입니다.
Base offset 트랜스폼 피봇 포인트와 관련한 충돌 실린더의 오프셋입니다.
스티어링
Speed 최대 이동 속도(초당 월드 단위로)
Angular Speed 최대 회전 속도(초당 각도)
Acceleration 최대 가속(제곱 초당 월드 단위로)
Stopping distance 에이전트는 목표 위치에 가까워졌을 정지합니다.
Auto Braking 활성화 에이전트는 목적지에 다다를 속도를 줄입니다. 에이전트가 멀티플 포인트 사이에서 부드럽게 움직여야 하는 순찰과 같은 동작을 때에는 반드시 비활성화 시켜야 합니다.
장애물 회피
Quality 장애물 회피 품질입니다. 에이전트의 수가 많다면 장애물 회피 품질을 줄임으로써 CPU 시간을 절약할 있습니다. 회피를 없음으로 설정할 경우 충돌만 해결할 있을 다른 에이전트와 장애물에 대한 적극적인 회피는 하지 않습니다.
Priority 낮은 우선 순위의 에이전트는 에이전트의 회피 대상에서 제외됩니다. 값은 0에서 99사이에서 설정되어야 하며 낮은 숫자가 높은 우선 순위임을 의미합니다.
경로 찾기
Auto Traverse OffMesh Link 자동적으로 오프 메시 링크를 횡단하려면 트루로 설정해야 합니다. 애니메이션을 사용하거나 오프메시 링크를 횡단하는 특정한 방법을 사용하고 싶다면 반드시 이를 꺼놔야 합니다.
Auto Repath 활성화 에이전트가 경로 일부분의 끝에 도달하면 경로를 재탐색 합니다. 목적지까지 경로가 없다면 목적지에서 제일 가깝게 도달할 있는 위치까지 부분적인 경로가 생성됩니다.
Area Mask 영역 마스크는 에이전트가 경로 탐색에 어떠한 영역 타입 고려할 것인지를 설명합니다. 내비메시 베이킹를 위해 메시를 준비할 각각의 메시 영역 타입을 설정할 있습니다. 예를 들어 계단을 특별한 영역 타입으로 표시하고 몇몇 캐릭터 타입의 계단 이용을 금지할 있습니다.

세부 정보

에이전트는 수직으로 서 있는 실린더에 의해 정의되며 실린더의 크기는 Radius  Height 프로퍼티에 의해 특정됩니다. 실린더는 오브젝트와 함께 움직이지만 오브젝트가 회전한다 해도 계속 수직으로 서 있습니다. 실린더의 모양은 다른 에이전트와 장애물간의 충돌 감지와 대응에 사용됩니다. 게임 오브젝트의 앵커 포인트가 실린더의 베이스에 없을 때 높이의 차이를 메우기 위해 베이스 오프셋 프로퍼티를 사용할 수 있습니다.

실린더의 높이와 반경은 실제로 두 개 의 다른 장소에 특정됩니다. 내비메시 베이크 설정과 각 에이전트의 프로퍼티 입니다.

내비메시 베이크 설정 은 내비메시 에이전트가 어떻게 정적인 월드 지오메트리와 충돌하고 또는 어떻게 회피하는지를 설명합니다. 메모리 여유량을 유지하고 CPU 로드를 지속적으로 체크하기 위해 오직 하나의 크기만이 베이크 설정에서 특정될 수 있습니다. -내비메시 에이전트 프로퍼티 값은 에이전트가 움직이는 장애물 및 다른 에이전트와 어떻게 충돌하는지를 설명합니다.

대부분의 경우 두 장소 모두에 에이전트 크기를 똑같이 설정합니다. 하지만 예를 들어 크기가 큰 에이전트의 반경이 더 넓다면 다른 에이전트는 그 에이전트 주변에 공간을 더 많이 남겨둡니다. 하지만 그렇지 않다면 크기가 큰 에이전트도 마찬가지로 환경을 무시합니다.

 

하이라키뷰에서 Player를 선택하고  TAG에서 PLAYER를 생성하고 적용한다

Nave Mesh Agent는 인스펙터에서 추적대상을 연결할 수 없고 스크립트를 생성해야한다.

MonsterCtrl스크립트를 생성하자.  Monster에 적용한다.

코드는 간단한다 다음한줄로 자동으로 추적한다. 다만 명령을 실행할 당시의 위치만이다. 명령실행후 플레이어가 움직이면 자동 갱신되지 않는다.

agent.destination = playerTr.position;

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;  //for Navigation

public class MonsterCtrl : MonoBehaviour
{
    private Transform monsterTr;
    private Transform playerTr;
    private NavMeshAgent agent;
    void Start()
    {
        monsterTr= GetComponent<Transform>();
        playerTr = GameObject.FindWithTag("PLAYER").GetComponent<Transform>();  
        agent = GetComponent<NavMeshAgent>();
        agent.destination = playerTr.position;  //목표를 플레이어로 설정
    }
}

잘 된다. 처음에는 PLAYER TAG를 Monster에도 설정했다가 뺑글뺑글 도는 걸 보고 풀어줬더니 잘되었다. PLAYER TAG는 Player에만

 

Monster는 NavMeshAgent가 미리 베이크된 NavMesh에 붙어서 이동하기 때문에 살짝 떠 있다. 방법은 NavMesh를 Bake할대 낮춰주던지 Monster NavMeshAgent의 BaseOffset을 -0.1로 낮춰주는 거다

오른쪽 BaseOffset이 -0.1 로 적용되어 있음
Monster가 NavMesh밑으로 가라앉어있다.

 

+ Recent posts