바닥, 장애물과 같은 게임 월드의 정보를 미리 저장해두고, 에이전트가 이동할 때 저장된 정보를 바탕으로 장애물을 피해 목표 위치까지 이동할 경로를 탐색함. 게임 월드에 네비게이션 매쉬를 설정하고, 이동 에이전트가 NavMeshAgent 컴포넌트를 기반으로 이동하도록 설정함
또한 OffMeshLink, NavMeshObstacle 등의 컴포넌트도 활용함
1. 강의 링크에 있는 미리 만들어둔 GameWorld 패키지를 import
2. GameWorld 프리팹을 씬에 배치함
3. Window - AI - Navigation (Obsolete)를 클릭해 Navigation View에서 Navigation Mesh를 설정함
4. Navigation View의 Object 탭을 누른 다음 Mesh Renderers를 클릭하고, 하이어라키에 있는 GameWorld 하위 항목을 모두 선택한 후 "Navigation Static" 변수를 체크해 Navigation Mesh 데이터로 사용 가능하게 함
5. Navigation View의 Bake 탭에서 "Bake" 버튼을 누르면, 현재 설정된 정보를 바탕으로 Navigation Mesh 데이터를 설정함
6. 3D Object - Capsule로 Player 오브젝트를 만들고 Material을 설정한 뒤, transform을 리셋하고 position을 (0,1,0)으로 변경
7. Player 오브젝트에 Nav Mesh Agent 컴포넌트를 추가
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class MoveMent3D : MonoBehaviour
{
[SerializeField]
private float moveSpeed = 5.0f;
private NavMeshAgent navMashAgent;
// Start is called before the first frame update
private void Awake()
{
navMashAgent = GetComponent<NavMeshAgent>();
}
// Update is called once per frame
public void MoveTo(Vector3 goalPosition)
{
// 기존에 이상 행동을 하고 있었다면 코루틴 중지
StopCoroutine("OnMove");
// 이동 속도 설정
navMashAgent.speed = moveSpeed;
// 목표 지점 설정 (목표까지의 경로 계산 후 알아서 움직임)
navMashAgent.SetDestination(goalPosition);
// 이동 행동에 대한 코루틴 시작
StartCoroutine("OnMove");
}
IEnumerator OnMove()
{
while (true)
{
// 목표 위치(navNeshAgent.detination)와 내 위치(transform.position)의 거리가 0.1 미만일때
// 즉, 목표 위치에 거의 도착했을때
if(Vector3.Distance(navMashAgent.destination, transform.position) < 0.1f)
{
// 내 위치를 목표 위치로 설정
transform.position = navMashAgent.destination;
// SetDestination()에 의해 설정된 경로를 초기화. 이동을 멈춘다
navMashAgent.ResetPath();
break;
}
yield return null;
}
}
}
우리가 보고 있는 화면은 2차원 모니터이고, 게임 세상은 3차원임.
즉, 2차원(2D) 화면을 통해 3차원(3D) 오브젝트를 제어해야 함
구현 원리:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private MoveMent3D movement3D;
private void Awake()
{
movement3D = GetComponent<MoveMent3D>();
}
// Update is called once per frame
private void Update()
{
// 마우스 왼쪽 버튼을 눌렀을때
if (Input.GetMouseButtonDown(0))
{
RaycastHit hit;
// Camera.main : 태그가 "Camera"인 오브젝트 = "Main Camera"
// 카메라로부터 마우스 좌표(Input.mousePosition)위치를 관통하는 광선 생성
// ray.origin : 광선 시작 위치
// ray.direction : 광선의 진행 방향
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
// Physics.Raycast() : 광선을 발사해서 부딪치는 오브젝트를 검출
// (광선에 부딪치는 오브젝트가 있으면 true 반환)
// ray.origin 위치로부터 ray.direction 방향으로 무한한 길이(Mathf.Infinity)의 광선 발사
// 광선에 부딪치는 오브젝트의 전보를 hit에 저장
if(Physics.Raycast(ray, out hit, Mathf.Infinity))
{
// hit.transform.position : 부딪힌 오브젝트의 위치
// hit.point : 광선과 오브젝트가 부딪힌 세부 위치
// hit.point를 목표 위치로 이동
movement3D.MoveTo(hit.point);
}
}
}
}
해당 포스트는 고박사, [ 따라하면서 배우는 고박사의 유니티 기초[유니티 2D 기초 (Unity 3D Basic)] ], (2020, 07월 06일) 인프런 강의를 참고하여 작성하였습니다.
Corner Unity
Editor : Hetbahn
[유니티 소소모임] 3주차. 유니티 에디터 배우기 2 (Editor : Ijin) (0) | 2024.11.08 |
---|---|
[유니티 소소모임] 3주차. 유니티 에디터 배우기 2 (Editor: Borybop) (0) | 2024.11.08 |
[유니티 소소모임] 3주차. 유니티 에디터 배우기 2 (Editor: Luna) (0) | 2024.11.08 |
[유니티 소소모임] 2주차. 유니티 에디터 배우기 1 (Editor: Hetbahn) (1) | 2024.10.11 |
[유니티 소소모임] 2주차. 유니티 에디터 배우기 1 (Editor: Borybop) (1) | 2024.10.11 |