VR 콘텐츠 기초

InMindVR - AI Navigation, NavMeshAgent, NavMeshSurface, WayPoint 이동

다모아 2023. 10. 18. 11:46

 

 


using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;

public class Player : MonoBehaviour
{
    [SerializeField] private Transform[] wayPoints;
    [SerializeField] protected float moveSpeed = 1f;
    protected Transform nextPoint;
    protected System.Action onMoveComplete;
    protected Coroutine coroutine;
    protected Queue<Transform> queue = new Queue<Transform>();

    void Start()
    {
        Debug.Log("Player Start");

        this.Init();

        //이동 완료 대리자 메서드 
        this.onMoveComplete = () =>
        {
            this.MoveContinue();
        };

        //시작시 큐에서 하나 꺼내고  
        this.nextPoint = this.queue.Dequeue();
        this.PrintQueue();
        //이동  
        this.Move();
    }

    protected void MoveContinue()
    {
        //큐를 확인 하고 있으면 큐에서 하나 꺼내서 이동 계속 없으면 이동완료
        if (this.queue.Count > 0)
        {
            this.nextPoint = this.queue.Dequeue();
            this.PrintQueue();
            this.Move();
        }
        else
        {
            Debug.Log("모든 이동을 완료 했습니다.");
        }
    }

    protected void Init()
    {
        //큐에 넣기 2-3-4-1
        for (int i = 1; i < this.wayPoints.Length; i++)
        {
            this.queue.Enqueue(this.wayPoints[i]);
        }
        this.queue.Enqueue(this.wayPoints[0]);
    }

    private void PrintQueue()
    {
        StringBuilder sb = new StringBuilder();
        foreach (var trans in this.queue)
        {
            sb.AppendFormat("{0} ", trans.name);
        }
        Debug.Log(sb.ToString());
    }

    protected virtual void Move()
    {
        Debug.LogFormat("{0}으로 이동합니다.", this.nextPoint.name);
        if (this.coroutine != null) StopCoroutine(this.coroutine);
        this.coroutine = this.StartCoroutine(this.CoMove());
    }

    private IEnumerator CoMove()
    {
        while (true)
        {
            this.transform.LookAt(this.nextPoint);
            this.transform.Translate(Vector3.forward * this.moveSpeed * Time.deltaTime);
            var dis = Vector3.Distance(this.nextPoint.position, this.transform.position);
            if (dis <= 0.1f)
                break;

            yield return null;
        }
        this.onMoveComplete();
    }
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class PlayerAI : Player
{
    [SerializeField] private NavMeshAgent agent;

    private void Start()
    {
        Debug.Log("PlayerAI Start");

        //대리자 인스턴스를 생성(메서드를 연결)하고
        this.onMoveComplete = () => {
            this.MoveContinue();
            Debug.Log("이동완료");
        };

        this.Init();

        //목표 위치를 설정

        //시작시 큐에서 하나 꺼내고
        this.nextPoint = this.queue.Dequeue();

        this.Move();
    }

    protected override void Move()
    {
        this.agent.SetDestination(this.nextPoint.position);

        if(this.coroutine != null)
        {
            StopCoroutine(this.coroutine);
        }
        this.coroutine = this.StartCoroutine(this.CoMove());
    }

    private IEnumerator CoMove()
    {
        while (true)
        {
            yield return null;

            if(agent.remainingDistance == 0)
            {
                break;
            }
        }
        this.onMoveComplete();
    }
}