Unity에서 캐릭터가 이동 / 탐색하기 위한 기능 구현
위와같이 구성된 맵에서 계단으로 가면 빠른지, Jump하여서 넘어가면 빠른지 등을 정해서 Agent에게 이동경로를 제공하는 것
시스템의 구성
- NavMesh:
- 걸어갈 수 있는 표면을 설명
- 한 위치에서 다른 위치로의 경로를 찾을 수 있는 데이터 구조
- 데이터 구조는 Level Geometry에서 자동으로 구축 혹은 Bake됨 - NavMesh Agent:
- NavMesh를 이용하여 탐색 이동할 수 있는 객체 - Off-Mesh Link:
- 보행이 불가능한 위치를 연결하기 위한 장치로 이용 - NavMesh Obstacle:
- 고정되어 있거나 동적인 방해물을 만들 수 있음
게임이 Runtime으로 돌아가기전에 Baking해서 사용함
Agent가 파란색으로 Baking된 구역을 돌아다닐 수 있는 구역으로, 어떠한 방법이 가장 최단거리인지 파악해서 이동함
Off-Mesh Link 같은 Component를 이용하여 점프같은 행동을 구현해줄 수 있음
2D같은 경우 A* PathFinding Algorithm을 구현해야 하며
3D는 Navigation을 사용하면 됨
일단 간단하게 지형을 제작해본다.
본인은 ProGrid와 ProBuilder를 이용하여 Plane과 Cube를 배치했음
Window -> AI -> Navigation을 클릭한다.
Navigation은 다음과 같은 탭이 있다.
Agents :
탐색 이동할 수 있는 객체를 정의할 수 있다. 기본적으로 Humanoid가 제공된다.
- Name : 객체의 이름
- Radius : 객체의 크기
- Height : 객체의 높이
- Step Height : 만약 계단같은 영역이 있다면, 건너갈 수 있는 계단 폭의 크기
- Max Slope : 이동할 수 있는 비탈면(경사면)의 최대 각도
Areas :
최단거리를 도출해 내야하는데, 이 때 각 영역의 Cost를 정하기
기본적으로 Walkable, Not Walkable, Jump가 제공되며 사용자가 직접 Name과 Cost를 작성할 수 있다.
Bake :
Bake를 할 때, 어떤 기준으로 Baking을 할지 설정해주는 곳 ( Agent와 비슷함 )
모든 Object들의 설정을 끝냈다면, Bake하여 NavMesh를 생성할 수 있음
Object :
실제로 경로 계산에 사용되는 오브젝트들을 설정하는 것
Mesh Renderers 또는 Terrains에 해당하는 Object들을 Hierarchy에서 선택하면 Object 탭에 자동으로 등록된다.
- Navigation Static : 정적인 오브젝트인가?
- Off-Mesh가 있다면 체크
- Navigation Area : Areas 탭에서 작성했던 영역들을 설정하는 곳
Plane을 Walkable로 설정하고, Cube를 NotWalkable로 설정한 후, Bake 한다.
생성된 NavMesh이다. Walkable Area의 색상이 하늘색이였으므로, 하늘색으로 영역이 표시되며
Not walkable한 Cube는 영역에서 벗어난다.
실제로 새로운 오브젝트가 생성됐을 땐, AI가 새로 생성된 오브젝트를 뚫게되니, Bake를 새로 해주어야 한다.
위의 Object에서 Navigation Static을 체크했다면, GameObject들은 Navigation Static으로 설정되게 된다.
다시 Cube를 Walkable로 변경해주고, Step Height가 0.25인 계단까지 생성하여 붙여주었다.
Bake를 하면, 계단에서 Cube까지 영역을 확장하는 것을 볼 수 있다.
이는 Bake에서 Step Height가 0.4로 지정되었기 때문에, 0.25인 계단을 Walkable 영역으로 지정할 수 있다.
다음은 이동할 객체인 Agent를 생성해보자.
실제로 움직일 Agent에 대해서 NavMeshAgent Component를 추가하면 된다.
본인은 Capsule에 NavMeshAgent Component를 추가했다.
- Agent Type : Navigation Mesh를 설정할 때, 생성했던 Agent 목록의 타입입니다.
- Base Offset : GameObject와 충돌 실린더의 높이 차이를 메꾸기 위해 사용됩니다.
즉 값이 높을 수록, 충돌 실린더가 아래로 내려갑니다.
Steering :
- Speed : GameObject의 최대 이동 속도
- Angular Speed : GameObject의 최대 회전 속도
- Acceleration : GameObject의 최대 가속도
- Stopping distance : 목표 위치에 가까워졌을 시 정지하는 거리
- Auto Braking : 활성화 상태라면, 목적지에 다다를 때 속도를 줄입니다.
해당 객체가 만약 순찰하는 것처럼 목표 지점을 순회해야한다면, 비활성화 해야합니다.
Obstacle Avoidance :
- Radius : 충돌 반경. 넓을 수록 좁은 폭을 지나갈 수 없습니다.
- Height : Agent가 장애물 밑으로 지나갈 수 있는 높이 간격입니다.
- Quality : 장애물 회피 품질입니다. 회피를 없음으로 설정하면 충돌만 체크되고 회피를 위한 동작을 하지 않습니다.
품질이 낮을 수록 CPU 자원이 절약됩니다.
- Priority : 회피의 우선순위입니다. 낮은 우선 순위의 Agent는 이 Agent의 회피 대상에서 제외됩니다.
0 ~ 99의 범위를 갖습니다.
Path Finding :
- Auto Traverse OffMesh Link : 활성화 상태라면, Off-Mesh Link를 이용하여 자동으로 점프하거나, 낙하합니다.
애니메이션을 사용하거나, 오프 메시 링크를 특정한 방법으로 사용하고 싶을 때는 비활성화 해야 합니다.
- Auto Repath : 활성화 상태라면, 에이전트가 경로 일부분의 끝에 도달하면 경로를 재탐색 합니다.
목적지까지 경로가 없다면, 목적지에서 제일 가깝게 도달할 수 있는 위치까지 부분적인 경로를 생성합니다.
- Area Mask : Navigation 에서 Areas 탭에 있는 레이어 리스트 중 선택하여 이동 경로를 제외시킬 수 있습니다.
이제 스크립트를 작성하여, 목적지를 정해준다.
Playable Object에 AddComponent하여 추가해주고, Target을 설정하여 Inspector상에서 추가해준다.
using UnityEngine;
using UnityEngine.AI;
public class Player : MonoBehaviour
{
private NavMeshAgent _agent;
[SerializeField]
private Transform target;
private void Awake()
{
_agent = GetComponent<NavMeshAgent>();
}
private void Update()
{
_agent.SetDestination(target.position);
}
}
그러면, Capsule GameObject가 Target GameObject까지 이동하는 것을 볼 수 있다.
Destination을 Update 함수내에서 설정해주었기 때문에, Runtime 상태에서 이동시켜도 Capsule이 따라온다.
Navigation 예제는
github.com/kimduuukbae/Today-I-Learned/tree/master/Unity3D/Navigation 에서 받아볼 수 있다.
'Unity3D > 기능' 카테고리의 다른 글
Unity3D) Firebase 연동 (0) | 2021.02.18 |
---|---|
Unity3D) Input System (0) | 2021.02.17 |
Unity3D) Navigation - 2 (0) | 2021.01.31 |