//重置导航数据信息 public void Reset() { open = true; G = 0; H = 0; thisGrid = null; preGrid = null; }
//查看是否节点在列表中 private NavigationData Exits(List <NavigationData> list, GridUnitData target) { for (int i = 0; i < list.Count; ++i) { if (list[i].thisGrid == target) { return(list[i]); } } return(null); }
public MapData(int height, int width) { mapWidth = width; mapHeight = height; gridUnitDatas = new GridUnitData[mapHeight, mapWidth]; for (int i = 0; i < mapHeight; ++i) { for (int j = 0; j < mapWidth; ++j) { gridUnitDatas[i, j] = new GridUnitData(i, j); } } }
//获取目标的所有可到达的相邻节点 public List <GridUnitData> GetNeighbor(GridUnitData target) { //定义方向数组 int[] dx = { 0, 1, 0, -1 }; int[] dy = { 1, 0, -1, 0 }; List <GridUnitData> neighbor = new List <GridUnitData>(); for (int i = 0; i < 4; ++i) { int x = target.row + dx[i], y = target.column + dy[i]; //越界或者是障碍则跳过 if (x < 0 || x >= mapHeight || y < 0 || y >= mapWidth || gridUnitDatas[x, y].gridType == GridType.Obstacle) { continue; } neighbor.Add(gridUnitDatas[x, y]); } return(neighbor); }
//取空的导航数据 private NavigationData GetEmptyNavigationData(GridUnitData thisGrid, NavigationData preGrid, int G, int H) { //优先从池中取 NavigationData nd = null; if (curUsedIdx < navigationDataPool.Count) { nd = navigationDataPool[curUsedIdx]; } else { nd = new NavigationData(); navigationDataPool.Add(nd); } ++curUsedIdx; nd.open = true; nd.G = G; nd.H = H; nd.thisGrid = thisGrid; nd.preGrid = preGrid; return(nd); }
//该单元格到目标单元格的曼哈顿距离 public int Distance(GridUnitData target) { return(Mathf.Abs(row - target.row) + Mathf.Abs(column - target.column)); }
///<summary> ///导航 ///</summary> ///<param name="mapData">地图数据</param> ///<param name="from">起点</param> ///<param name="to">终点</param> ///<param name="path">路径</param> ///<param name="searched">搜索过但为采用的节点</param> public bool Navigate(MapData mapData, GridUnitData from, GridUnitData to, out List <GridUnitData> path, out List <GridUnitData> searched) { //输出参数赋初值 path = new List <GridUnitData>(); searched = new List <GridUnitData>(); //没有地图则结束导航 if (mapData == null) { Debug.Log("mapData is null!"); return(false); } if (from == null || to == null) { Debug.Log("from or to is null!"); return(false); } //open储存将要探索的节点 List <NavigationData> open = new List <NavigationData>(); //close储存已经探索的节点 List <NavigationData> close = new List <NavigationData>(); //1.把起点加入open open.Add(GetEmptyNavigationData(from, null, 0, from.Distance(to))); int trytimes = 999; while (trytimes-- != 0) { //2.判断open列表,如果为空则搜索失败,如果终点在里面则搜索成功 if (open.Count == 0) { return(false); } NavigationData temp = Exits(open, to); if (temp != null) { //从终点回溯至起点 while (temp != null) { path.Add(temp.thisGrid); temp = temp.preGrid; } for (int i = 0; i < close.Count; ++i) { searched.Add(close[i].thisGrid); } return(true); } //3.从open列表取出F值最小的节点,将其设为当前节点,并加入close列表中 NavigationData nowGrid = open[0]; int minF = open[0].F, minH = open[0].H; for (int i = 1; i < open.Count; ++i) { if (open[i].F < minF || (open[i].F == minF && open[i].H < minH)) { nowGrid = open[i]; minF = open[i].F; minH = open[i].H; } } close.Add(nowGrid); open.Remove(nowGrid); //Debug.Log(nowGrid.thisGrid.row + "|" + nowGrid.thisGrid.column + " " + nowGrid.G + ',' + nowGrid.H + ',' + nowGrid.F); //4.获取当前节点的所有可到达节点 List <GridUnitData> neighbor = mapData.GetNeighbor(nowGrid.thisGrid); //对于每个节点 for (int i = 0; i < neighbor.Count; ++i) { //4.1 如果该节点在close列表中,删除open中的该节点 NavigationData t = Exits(close, neighbor[i]); if (t != null) { open.Remove(t); continue; } t = Exits(open, neighbor[i]); //int G = from.Distance(neighbor[i]); int G = nowGrid.G + 1; int H = to.Distance(neighbor[i]); //4.2 如果该节点不在open中,计算G,H值,设置父节点为当前节点,加入open列表 if (t == null) { NavigationData target = GetEmptyNavigationData(neighbor[i], nowGrid, G, H); open.Add(target); } //4.3 如果该节点在open中且以当前节点求F值更小,则更新G,H,设父节点为当前节点 else if (t.F > G + H) { t.G = G; t.H = H; t.preGrid = nowGrid; } } } return(false); }