//是否有共边节点,是的话返回该节点,否则返回空。参数为边 NavTriangle GetLinkNode(Vector3[] rim, NavTriangle except) { for (int i = 0; i < triangleList.Count; i++) { if (triangleList[i].Equals(except)) { continue; } Vector3[] verts = triangleList[i].verts; //共顶点数量 int count = 0; for (int j = 0; j < 3; j++) { if (verts[j] == rim[0]) { count++; } if (verts[j] == rim[1]) { count++; } } if (count == 2) { return(triangleList[i]); } } return(null); }
bool IsCloseListContains(NavTriangle navNode) { for (int i = 0; i < closeList.Count; i++) { if (closeList[i].node.center == navNode.center) { return(true); } } return(false); }
//取两个三角形的邻边两点 public static List <Vector3> GetTwoPointsInTwoPath(PathNode p1, PathNode p2) { NavTriangle n1 = p1.node; NavTriangle n2 = p2.node; List <Vector3> pointList = new List <Vector3>(); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (n1.verts[i] == n2.verts[j]) { pointList.Add(n1.verts[i]); } } } if (pointList.Count == 2) { //Vector3 v1 = pointList[0] - origin; //Vector3 v2 = pointList[1] - origin; Vector3 v1 = pointList[0] - p1.node.center; Vector3 v2 = pointList[1] - p1.node.center; Vector3 m = Vector3.Cross(v1, v2); //调成顺时针方向。 if (m.z > 0) { Vector3 tempP = pointList[0]; pointList[0] = pointList[1]; pointList[1] = tempP; } //Debug.Log("向量:" + m); return(pointList); } return(null); }
//初始化三角形相邻关系 void InitTriangleList() { for (int i = 0; i < triangleList.Count; i++) { NavTriangle node = triangleList[i]; //设置相邻三角形 Vector3[] verts = node.verts; node.nodeArr[0] = GetLinkNode(new Vector3[] { verts[0], verts[1] }, node); node.nodeArr[1] = GetLinkNode(new Vector3[] { verts[0], verts[2] }, node); node.nodeArr[2] = GetLinkNode(new Vector3[] { verts[1], verts[2] }, node); //设置相邻三角形的距离 for (int j = 0; j < 3; j++) { if (node.nodeArr[j] != null) { node.dis[j] = Vector3.Distance(node.center, node.nodeArr[j].center); } } } }
//初始化顶点列表 void SetVertexList() { vertsList.Clear(); triangleList.Clear(); int count = transform.childCount; for (int i = 0; i < count; i++) { Transform child = transform.GetChild(i); Vector3[] verts = new Vector3[child.childCount]; int countG = child.childCount; List <Vector3> posList = new List <Vector3>(); for (int j = 0; j < countG; j++) { Vector3 pos = child.GetChild(j).transform.position; posList.Add(pos); } vertsList.AddRange(posList); //设置各节点的顶点 for (int k = 0; k < posList.Count - 2; k++) { //保存节点信息 NavTriangle node = new NavTriangle(posList[0], posList[k + 1], posList[k + 2]); node.verts = new Vector3[] { posList[0], posList[k + 1], posList[k + 2] }; if (node == null) { print("空节点"); } triangleList.Add(node); } } }
static void Export() { Debug.Log("ExportNavMesh"); UnityEngine.AI.NavMeshTriangulation tmpNavMeshTriangulation = UnityEngine.AI.NavMesh.CalculateTriangulation(); //新建文件 string tmpPath = Application.dataPath + "/" + SceneManager.GetActiveScene().name + ".lua"; Debug.Log("=====================" + tmpPath + tmpNavMeshTriangulation.vertices.Length); StreamWriter tmpStreamWriter = new StreamWriter(tmpPath); tmpStreamWriter.WriteLine("-------本文件是地图导航网格文本"); tmpStreamWriter.WriteLine("local nav_triangle = {"); Hashtable pointTable = new Hashtable(); //顶点 for (int i = 0; i < tmpNavMeshTriangulation.vertices.Length; i++) { //tmpStreamWriter.WriteLine("v " + tmpNavMeshTriangulation.vertices[i].x + " " + tmpNavMeshTriangulation.vertices[i].y + " " + tmpNavMeshTriangulation.vertices[i].z); if (!pointTable.ContainsKey(tmpNavMeshTriangulation.vertices[i])) { pointTable.Add(tmpNavMeshTriangulation.vertices[i], new ArrayList()); } (pointTable[tmpNavMeshTriangulation.vertices[i]] as ArrayList).Add(i); } //tmpStreamWriter.WriteLine("g pPlane1"); Hashtable lineTable = new Hashtable(); List <NavTriangle> triangles = new List <NavTriangle>(); int triangleIndex = 1; for (int i = 0; i < tmpNavMeshTriangulation.indices.Length;) { //tmpStreamWriter.WriteLine("f " + (tmpNavMeshTriangulation.indices[i] + 1) + " " + (tmpNavMeshTriangulation.indices[i + 1] + 1) + " " + (tmpNavMeshTriangulation.indices[i + 2] + 1)); NavTriangle item = new NavTriangle(); item.tLineKeyArr = new string[3]; item.tIndex = triangleIndex; SetTriangleInfo(0, tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[i + 2]] , tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[i + 1]] , pointTable, item, lineTable); SetTriangleInfo(1, tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[i + 1]] , tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[i]] , pointTable, item, lineTable); SetTriangleInfo(2, tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[i + 2]] , tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[i]] , pointTable, item, lineTable); triangles.Add(item); triangleIndex += 1; i = i + 3; } for (int i = 0; i < triangles.Count; i++) { tmpStreamWriter.WriteLine(string.Format("\t[{0}] = {{", triangles[i].tIndex)); tmpStreamWriter.WriteLine(string.Format("\t\tv = {{{{{0}, {1}, {2}}}, {{{3}, {4}, {5}}},{{{6}, {7}, {8}}}}}," , tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[(triangles[i].tIndex - 1) * 3 + 2]].x, tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[(triangles[i].tIndex - 1) * 3 + 2]].z, tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[(triangles[i].tIndex - 1) * 3 + 2]].y , tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[(triangles[i].tIndex - 1) * 3 + 1]].x, tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[(triangles[i].tIndex - 1) * 3 + 1]].z, tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[(triangles[i].tIndex - 1) * 3 + 1]].y , tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[(triangles[i].tIndex - 1) * 3]].x, tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[(triangles[i].tIndex - 1) * 3]].z, tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[(triangles[i].tIndex - 1) * 3]].y)); tmpStreamWriter.WriteLine(string.Format("\t\tnedge = {{{0}, {1}, {2}}}," , GetSameLine(triangles[i].tLineKeyArr[0], triangles[i].tIndex, lineTable) , GetSameLine(triangles[i].tLineKeyArr[1], triangles[i].tIndex, lineTable) , GetSameLine(triangles[i].tLineKeyArr[2], triangles[i].tIndex, lineTable))); tmpStreamWriter.WriteLine("\t},\n"); } tmpStreamWriter.WriteLine("}"); tmpStreamWriter.Flush(); tmpStreamWriter.Close(); Debug.Log("ExportNavMesh Success"); }
public static void SetTriangleInfo(int index, Vector3 pos1, Vector3 pos2, Hashtable pointTable, NavTriangle item, Hashtable lineTable) { int point1, point2; string lineKey; point1 = Convert.ToInt32((pointTable[pos1] as ArrayList)[0]); point2 = Convert.ToInt32((pointTable[pos2] as ArrayList)[0]); lineKey = point1 < point2?string.Format("{0}_{1}", point1, point2) : string.Format("{0}_{1}", point2, point1); item.tLineKeyArr[index] = lineKey; if (!lineTable.ContainsKey(lineKey)) { lineTable.Add(lineKey, new ArrayList()); } (lineTable[lineKey] as ArrayList).Add(item.tIndex); }
void FindNextPath(PathNode start, NavTriangle endNode, List <PathNode> openList, List <PathNode> closeList) { for (int i = 0; i < 3; i++) { if (start == null) { Debug.Log("是空的"); } if (start.node.nodeArr[i] == null || IsCloseListContains(start.node.nodeArr[i])) { continue; } float g = start.dis + start.node.dis[i]; float h = Vector3.Distance(start.node.nodeArr[i].center, endNode.center); float f = g + h; PathNode path = new PathNode(); path.node = start.node.nodeArr[i]; path.dis = f; path.parent = start; openList.Add(path); } //取最小F节点,加入闭合列表 for (int i = 0; i < openList.Count; i++) { for (int j = i + 1; j < openList.Count; j++) { if (openList[i].dis > openList[j].dis) { PathNode path = openList[i]; openList[i] = openList[j]; openList[j] = path; } } } //如果最小路径是错误的路径,则标记错误。 PathNode curPath = null; if (openList.Count > 0) { curPath = openList[0]; openList.RemoveAt(0); closeList.Add(curPath); //将结束点加入闭合列表中 if (openList == null) { Debug.Log("是空的"); } if (curPath.node.center == endNode.center) { //PathNode path = new PathNode(); //path.node = endNode; //path.parent = curPath; //closeList.Add(path); return; } } FindNextPath(curPath, endNode, openList, closeList); }
public List <PathNode> FindCenterPointPath(Vector3 start, Vector3 end) { //标记开始结束点 startVertex = FindNodeByPoint(start); endVertex = FindNodeByPoint(end); if (startVertex == null && endVertex == null) { return(null); } else if (startVertex == null) { startVertex = FindNearestNode(start); } else if (endVertex == null) { endVertex = FindNearestNode(end); } PathNode startNode = new PathNode(); startNode.node = startVertex; PathNode endNode = new PathNode(); endNode.node = endVertex; //如果起点和终点在同一个三角形中,则返回一个节点 if (startVertex.center == endVertex.center) { pathList.Clear(); pathList.Add(startNode); return(pathList); } //如果起点和终点在两个相邻的三角形中,则返回二个节点 else if (TriangleUtil.GetTwoPointsInTwoPath(startNode, endNode) != null) { pathList.Clear(); pathList.Add(startNode); pathList.Add(endNode); return(pathList); } List <PathNode> openList = new List <PathNode>(); closeList = new List <PathNode>(); PathNode path = new PathNode(); path.node = startVertex; path.dis = 0; closeList.Add(path); FindNextPath(path, endVertex, openList, closeList); //记录并显示路径 if (showProcessPath) { ShowProcessPath(); } else { ShowCenterPath(); } return(pathList); }