public void changepath(Vector3 s, Vector3 e) { grid.NodeItem StartNode = Grid.GetGrid(s); //将开始和结束的坐标转换成节点坐标 grid.NodeItem EndNode = Grid.GetGrid(e); //定义开启列表和关闭列表 //开启列表:存储可以成为下一个父节点的节点 //关闭列表:存储成为过父节点的节点 List <grid.NodeItem> OpenList = new List <grid.NodeItem>(); HashSet <grid.NodeItem> CloseList = new HashSet <grid.NodeItem>(); OpenList.Add(StartNode); while (OpenList.Count > 0) { //将开启列表的第一个节点记录下来 grid.NodeItem ParentNode = OpenList[0]; //遍历开启列表寻找parent for (int i = 0; i < OpenList.Count; i++) { //若开启列表中的节点的总花费更小或不变并且到终点的花费更小 if (OpenList[i].fCost <= ParentNode.fCost && OpenList[i].gCost < ParentNode.gCost) { ParentNode = OpenList[i]; } } //将找到的父节点从开启列表中删除,加入关闭列表 OpenList.Remove(ParentNode); CloseList.Add(ParentNode); //若父节点为终点节点则停止更新路程花费并且生成路径 if (ParentNode == EndNode) { //生成路径 ShowPath(StartNode, EndNode); return; } // 判断周围节点,选择一个最优的节点 foreach (var item in Grid.GetNearNode(ParentNode)) { // 如果是墙或者已经在关闭列表中 if (item.isWall || CloseList.Contains(item)) { continue; } // 计算当前相领节点现开始节点距离 int newCost = ParentNode.gCost + updatecost(ParentNode, item); // 如果距离更小,或者原来不在开始列表中 if (newCost < item.gCost || !OpenList.Contains(item)) { // 更新与开始节点的距离 item.gCost = newCost; // 更新与终点的距离 item.hCost = updatecost(item, EndNode); // 更新父节点为当前选定的节点 item.parent = ParentNode; // 如果节点是新加入的,将它加入打开列表中 if (!OpenList.Contains(item)) { OpenList.Add(item); } } } } ShowPath(StartNode, null); }