김김김의 게임개발
  • 유니티 게임 개발 NavMesh
    2023년 09월 21일 23시 09분 39초에 업로드 된 글입니다.
    작성자: noun06
    • 3D 공간을 평면으로 분할하고 각각의 평면을 네비게이션 셀이라고 부르는 다각형 형태로 나타냄. 이를 통해 캐릭터들이 이동 가능하거나 불가능한 지역을 정의하고 이를 기반으로 이동 경로를 계산할 수 있음.
    using UnityEngine;
    using UnityEngine.AI;
    
    public class CharacterMovement : MonoBehaviour
    {
        public Transform target; // 목적지로 이동할 위치
        private NavMeshAgent navMeshAgent; // NavMeshAgent 컴포넌트
    
        void Start()
        {
            navMeshAgent = GetComponent<NavMeshAgent>();
            
            if (navMeshAgent == null)
            {
                Debug.LogError("No NavMeshAgent");
            }
            else if (target != null)
            {
                // NavMeshAgent에 목적지 설정
                navMeshAgent.SetDestination(target.position);
            }
            else
            {
                Debug.LogError("No Target Destination");
            }
        }
    
        void Update()
        {
            // 이동 중인지 체크하고 필요한 동작 수행
            if (navMeshAgent.remainingDistance <= navMeshAgent.stoppingDistance)
            {
                // 목적지에 도착했을 때 수행할 동작을 여기에 추가
                Debug.Log("Arrived");
            }
        }
    }

     

    • 경로 탐색 알고리즘은 캐릭터의 현재 위치에서 목표 지점까지 가장 적절한 경로를 찾는 알고리즘임. 주로 다음과 같은 A*알고리즘 등이 사용됨.
    • target을 통해 목적지 위치를 설정 후 Start 메서드에서 Seeker 컴포넌트를 초기화 함. 이후 StartPath()를 사용하여 에이스타 알고리즘을 시작하여 경로를 계산. OnPathComplete()에서 경로 계산이 완료되면 계산된 경로를 저장. Update 메서드에서 계산된 경로를 따라 캐릭터를 이동시킴.
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using Pathfinding;
    
    public class CharacterMovement : MonoBehaviour
    {
        public Transform target; // 목적지로 이동할 위치
        private Seeker seeker; // 경로 탐색을 수행하는 컴포넌트
        private Path path; // 계산된 경로
        private int currentWaypoint = 0; // 현재 경로의 인덱스
        public float speed = 5f; // 이동 속도
        public float nextWaypointDistance = 1f; // 다음 웨이포인트까지의 거리
    
        void Start()
        {
            seeker = GetComponent<Seeker>();
            
            if (seeker == null)
            {
                Debug.LogError("No Seeker");
            }
            else if (target != null)
            {
                // 경로 계산 시작
                seeker.StartPath(transform.position, target.position, OnPathComplete);
            }
            else
            {
                Debug.LogError("No Target Destination");
            }
        }
    
        void OnPathComplete(Path p)
        {
            if (!p.error)
            {
                path = p;
                currentWaypoint = 0;
            }
        }
    
        void Update()
        {
            if (path == null)
            {
                return;
            }
    
            if (currentWaypoint >= path.vectorPath.Count)
            {
                // 경로의 끝에 도달한 경우
                return;
            }
    
            // 다음 웨이포인트로 이동
            Vector3 direction = (path.vectorPath[currentWaypoint] - transform.position).normalized;
            Vector3 moveAmount = direction * speed * Time.deltaTime;
            transform.Translate(moveAmount);
    
            // 다음 웨이포인트까지의 거리를 체크하여 다음 웨이포인트로 이동
            if (Vector3.Distance(transform.position, path.vectorPath[currentWaypoint]) < nextWaypointDistance)
            {
                currentWaypoint++;
            }
        }
    }
    댓글