【Unity】ナビメッシュの経路を取得して再利用する #1

投稿者: | 2020-07-22

ナビメッシュの経路を保存しておいて、別の目的地を設定した後に再設定してみます。

経路は目的地を設定してから数フレーム後に利用可能になるようです。まだ一度も目的地を設定していないときは、今いる場所が目的地になっていて、経路のコーナーポイントもその一つだけです。NavMeshAgent.pathPendingはfalseになっています。

ナビメッシュエージェントに付けたスクリプトでは、マウスクリックで目的地を設定し、経路を取得してリストにいれていきます。この時にコーナーポイントに緑色の球を置きますが、2番目の経路のときだけピンクの球にします。

そして、Eキーを押すと2番目の経路をナビメッシュエージェントに再設定します。このときのコーナーポイントに黄色い球を置くと、もとのコーナーポイントではなく、2番目の経路に戻ってから目的地へ向かうためのコーナーポイントが設定されるのがわかります。

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

public class PathTest : MonoBehaviour
{
    [SerializeField] GameObject sphere;
    [SerializeField] GameObject sphere1;
    [SerializeField] GameObject sphere2;

    NavMeshAgent agent;
    List paths;
    bool havePath = false;
    Plane groundPlane;
    float rayDistance;
    public float planeDistance = 0f;
    Vector3[] corners;

    // Start is called before the first frame update
    void Start()
    {
        agent = GetComponent<NavMeshAgent>();
        paths = new List<NavMeshPath>();
        groundPlane = new Plane(Vector3.up, planeDistance);
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0)) // 左クリック
        {
            agent.destination = GetCursorPosition3D(); // 目的地を設定
            havePath = false;
        }
        
        if (!havePath && !agent.pathPending)
        {
            // 緑の球を削除
            GameObject[] greenSpheres = GameObject.FindGameObjectsWithTag("GreenSphere");

            if (greenSpheres.Length != 0)
            {
                foreach (GameObject s in greenSpheres)
                {
                    Destroy(s);
                }
            }

            // 黄色の球を削除
            GameObject[] yellowSphere = GameObject.FindGameObjectsWithTag("YellowSphere");

            if (yellowSphere.Length != 0)
            {
                foreach (GameObject s in yellowSphere)
                {
                    Destroy(s);
                }
            }

            havePath = true;
            NavMeshPath path = agent.path;
            paths.Add(path);           
            corners = path.corners; // コーナーポイントを取得

            // コーナーポイントに緑の球を配置
            for (int i = 0; i < corners.Length; i++)
            {
                if (paths.Count == 2)
                {
                    // 2つ目の時はピンクの球を配置
                    Instantiate(sphere1, corners[i], sphere.transform.rotation);

                }
                else { // 緑の球を配置
                    Instantiate(sphere, corners[i], sphere.transform.rotation);
                }
            }          
        }

        if (Input.GetKeyDown(KeyCode.E))
        {
            // 緑の球を削除
            GameObject[] greenSpheres = GameObject.FindGameObjectsWithTag("GreenSphere");

            if (greenSpheres.Length != 0)
            {
                foreach (GameObject s in greenSpheres)
                {
                    Destroy(s);
                }
            }

            agent.path = paths[1]; // 2つめのパスを設定

            corners = agent.path.corners; // コーナーポイントを取得

            // コーナーポイントに緑の球を配置
            for (int i = 0; i < corners.Length; i++)
            {
                // 黄色の球を配置
                Instantiate(sphere2, corners[i], sphere.transform.rotation);

            }
        }
        
    }

    Vector3 GetCursorPosition3D()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); // マウスカーソルから、カメラが向く方へのレイ
        groundPlane.Raycast(ray, out rayDistance); // レイを飛ばす

        return ray.GetPoint(rayDistance); // Planeとレイがぶつかった点の座標を返す
    }
}

再設定する経路から遠くにいるとその場で立ち止まってしまいました。近づいてから再設定するとまたその経路へ戻れるようになりました。止まってもエラーになるわけではありません。

再設定する経路上にいれば問題なく戻れますが、経路上にいないときは、毎回その経路のスタート地点の近くに戻るような感じです。

コメントを残す

メールアドレスが公開されることはありません。