核心原理是,获取导航网格上的一个网格三角形,然后获取这个网格三角形 上的随机点(对逐个两个顶点之间获取插值)
/// <summary> /// 获取随机位置 /// </summary> /// <returns></returns> public Vector3 GetRandomPoint() { NavMeshTriangulation navMeshData = NavMesh.CalculateTriangulation(); int t = Random.Range(0, navMeshData.indices.Length - 3); Vector3 point = Vector3.Lerp(navMeshData.vertices[navMeshData.indices[t]], navMeshData.vertices[navMeshData.indices[t + 1]], Random.value); point = Vector3.Lerp(point, navMeshData.vertices[navMeshData.indices[t + 2]], Random.value); return point; } /// <summary> /// 获取一个高精度的范围外随机点 /// </summary> /// <param name="targetPoint"></param> /// <param name="distance"></param> /// <param name="success"></param> /// <returns></returns> public Vector3 GetRandomRangePointWithHighPrecision(Vector3 targetPoint, float distance, out bool success) { NavMeshTriangulation navMeshData = NavMesh.CalculateTriangulation(); List<int> list = new List<int>(); //获取所有三角的第一个顶点的索引值 for (int i = 0; i < navMeshData.indices.Length-3; i++) list.Add(i); int count = list.Count; Debug.Log("顶点数量:" + navMeshData.indices.Length); List<Vector3> triangle = new List<Vector3>(); for (int i = 0; i < count; i++) { //判断当前的顶点是否在列表中,并且该顶点的另外两个顶点是否在列表中(如果不在,表示已经被判断过,并且不符合条件) int index = Random.Range(0, list.Count); if (Vector3.Distance(targetPoint, navMeshData.vertices[navMeshData.indices[list[index]]]) > distance) triangle.Add(navMeshData.vertices[navMeshData.indices[list[index]]]); if (list.Contains(list[index] + 1)&&Vector3.Distance(targetPoint, navMeshData.vertices[navMeshData.indices[list[index] + 1]]) > distance) triangle.Add(navMeshData.vertices[navMeshData.indices[list[index] + 1]]); if (list.Contains(list[index] + 2)&&Vector3.Distance(targetPoint, navMeshData.vertices[navMeshData.indices[list[index] + 2]]) > distance) triangle.Add(navMeshData.vertices[navMeshData.indices[list[index] + 2]]); if (triangle.Count > 0) break; list.RemoveAt(index); } Vector3 point = Vector3.zero; success = false; if (triangle.Count > 0) { point = GerLerpPoint(triangle); success = true; } return point; } /// <summary> /// 获取远离tartgetPoint的点 /// </summary> /// <param name="tartpoint"></param> /// <returns></returns> public Vector3 GetRandomEscapPoint(Vector3 targetPoint,float distance,out bool success) { NavMeshTriangulation navMeshData = NavMesh.CalculateTriangulation(); List<int> list = new List<int>(); //获取所有三角的第一个顶点的索引值 for(int i = 0; i < navMeshData.indices.Length; i+=3) list.Add(i); int count = list.Count;Debug.Log("顶点数量:"+navMeshData.indices.Length); List<Vector3> triangle=new List<Vector3>(); for(int i = 0; i < count; i++) { int index = Random.Range(0, list.Count); if (Vector3.Distance(targetPoint, navMeshData.vertices[navMeshData.indices[list[index]]]) > distance) triangle.Add(navMeshData.vertices[navMeshData.indices[list[index]]]); if (Vector3.Distance(targetPoint, navMeshData.vertices[navMeshData.indices[list[index] + 1]]) > distance) triangle.Add(navMeshData.vertices[navMeshData.indices[list[index] + 1]]); if (Vector3.Distance(targetPoint, navMeshData.vertices[navMeshData.indices[list[index] + 2]]) > distance) triangle.Add(navMeshData.vertices[navMeshData.indices[list[index] + 2]]); if (triangle.Count > 0) break; list.RemoveAt(index); } Vector3 point = Vector3.zero; success = false; if (triangle.Count > 0) { point = GerLerpPoint(triangle); success = true; } return point; } //获取多个顶点之间的一个随机点 Vector3 GerLerpPoint(List<Vector3> list) { Vector3 point = list[0]; foreach(Vector3 v in list) { point = Vector3.Lerp(point, v, Random.value); } return point; }