【Unity】ナビメッシュの経路の長さを表示する

投稿者: | 2020-07-23

ナビメッシュエージェントから目的地までの経路に沿った距離を表示してみます。

ナビメッシュの経路のコーナーポイントは、通過するたびに一つずつ減っていくようです。今ある2番目のコーナーポイントを通過すると、1番目のコーナーポイントが削除されます。

なので、コーナーポイントを順番にみていって、隣り合うコーナーポイントの間の距離を足し合わせました。2番目のときはナビメッシュエージェントとの距離を使います。

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

public class PathLengthTest : MonoBehaviour
{
    [SerializeField] GameObject sphere;
    [SerializeField] Text text;

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

    int previousCornersLength = 0;
    

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

    // Update is called once per frame
    void Update()
    {
        if (corners != default)
        {

            // コーナーポイントの数が変われば球を置き直す
            if (previousCornersLength != agent.path.corners.Length)
            {

                // 緑の球を削除
                GameObject[] greenSpheres = GameObject.FindGameObjectsWithTag("GreenSphere");

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

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

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

                }

            }

            // 経路ののこりの長さを表示
            corners = agent.path.corners; // コーナーポイントを取得
            float pathLength = 0f;
            Vector3 agentPos = transform.position;

            for (int i = 1; i < corners.Length;i++)
            {
                if (i == 1)
                {
                    pathLength += Vector3.Distance(corners[i], agentPos);
                }
                else {
                    pathLength += Vector3.Distance(corners[i], corners[i - 1]);

                }
            }

            text.text = Mathf.Floor(pathLength * 10) / 10 + "m";
        }


        // 左クリックで目的地を設定
        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);
                }
            }


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

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

            }
        }

        previousCornersLength = corners.Length;
    }

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

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

反対方向の目的地を設定して、ナビメッシュエージェントが1番目のコーナーポイントを新しい目的地と逆方向に通り過ぎてしまったときも1番目を無視しますがあまり問題ないと思います。

コメントを残す

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