前提・実現したいこと
タイトルの通り、NavmeshAgentに高低差のあるマップ内で到達可能な座標をランダムで渡してあげたいです。
マップは高低差があり、形が変わったりはしないです。
実装は出来ているのですが、さらにいい方法が無いかお聞きしたいです。
2通りの実装が出来ていますが、それぞれ欠点があり悩んでいます。
1つ目
マップ内の大きさを取って置き、その範囲からランダムで決める
メリット:
マップの四隅?が分かればその範囲内でランダムで座標を決められる
デメリット:
マップの四隅の隅々までnavmeshがあるならともかく
高低差があったり範囲内に隙間が多くなったりすると複数検索を掛けなくてはならず結構処理も重くなる
2つ目
マップ内に予め目的地候補のオブジェクトを置いてそこからランダムで選ぶ
メリット:
自分でマップ周辺に置いてあるので余程外した位置に置かなければ1回の検索で100%当てられる
デメリット:
予めオブジェクトを置くのが大変
今後マップは拡張していくのでその度にオブジェクト追加するのは...とか思ってます。
マップ内に予め目的地候補のオブジェクトを置いてそこからランダムで選ぶ
今行っている実装方法
一つ目の方法
using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; // マップ内の大きさを取って置き、その範囲からランダムで決める public class AutoMove : MonoBehaviour { private Vector3 nagativeMapRange = new Vector3(-9f, 0, -19f); private Vector3 positiveMapRange = new Vector3(27f, 6, 19f); private NavMeshAgent agent; private float searchRange = 1f; private int maxSearchCount = 100; private void Start() { agent = GetComponent<NavMeshAgent>(); agent.isStopped = false; } private void Update() { if (agent.hasPath == false && agent.pathPending == false) { agent.destination = GetNextDestination(); } } // 次の目的地を探す // ランダムで座標を決めるので複数回チャレンジする // 1回の時もあれば30回探す時も... private Vector3 GetNextDestination() { NavMeshHit navMeshHit; for (int i = 0; i < maxSearchCount; i++) { Vector3 rndPos = new Vector3( Random.Range(nagativeMapRange.x, positiveMapRange.x), Random.Range(nagativeMapRange.y, positiveMapRange.y), Random.Range(nagativeMapRange.z, positiveMapRange.z)); if (NavMesh.SamplePosition(rndPos, out navMeshHit, searchRange, NavMesh.AllAreas) == true) { Debug.Log($"{i}回目で目的地発見"); return navMeshHit.position; } } Debug.LogWarning("目的地見つからなかった★"); return Vector3.zero; } }
二つ目の方法
using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; // マップ内に予め目的地候補のオブジェクトを置いてそこからランダムで選ぶ public class AutoMove : MonoBehaviour { private List<Vector3> destinationPoints = new List<Vector3>(); private NavMeshAgent agent; private System.Random rnd = new System.Random(); private int destParentChildCount; private float searchRange = 1f; private void Start() { agent = GetComponent<NavMeshAgent>(); Transform destParent = GameObject.FindGameObjectWithTag("DestinationParent").transform; destParentChildCount = destParent.childCount; for (int i = 0; i < destParentChildCount; i++) { destinationPoints.Add(destParent.GetChild(i).transform.position); } } private void Update() { if (agent.hasPath == false && agent.pathPending == false) { agent.destination = GetNextDestination(); } } // 次の目的地を探す // 余程でたらめな場所に置かなければ反応する private Vector3 GetNextDestination() { int rndIndex = rnd.Next(0, destParentChildCount - 1); Vector3 targetPoint = destinationPoints[rndIndex]; NavMeshHit navMeshHit; if (NavMesh.SamplePosition(targetPoint, out navMeshHit, searchRange, NavMesh.AllAreas) == true) { Debug.Log("目的地発見"); return navMeshHit.position; } Debug.LogWarning("目的地見つからなかった★"); return Vector3.zero; } }

回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/07/07 06:39
2021/07/07 09:59
2021/07/08 00:56