private List <路径区块> 寻找周围路径(路径区块 中心路径点, List <路径区块> 关闭列表, 路径区块[,] 导航数据, AI导航 请求者) { List <路径区块> 列表 = new List <路径区块>(); for (int i = 0; i < 9; i++) { int x = 中心路径点.x - 导航数据[0, 0].x; int y = 中心路径点.y - 导航数据[0, 0].y; switch (i) { case 0: break; case 1: y++; break; case 2: x++; break; case 3: y--; break; case 4: x--; break; case 5: x++; y++; break; case 6: x++; y--; break; case 7: x--; y--; break; case 8: x--; y++; break; } try { if (!导航数据[x, y].障碍物 && !关闭列表.Contains(导航数据[x, y])) { #if 可视化 if (请求者.调试模式) { 导航烘焙.烘焙数据[x + 导航数据[0, 0].x, y + 导航数据[0, 0].y].GetComponent <SpriteRenderer>().color = Color.green; } #endif 列表.Add(导航数据[x, y]); } } catch { continue; } } return(列表); }
public 导航数据(AI导航 发起人, 路径区块[,] 地图数据, 路径区块 起点) { this.发起人 = 发起人; this.地图数据 = 地图数据; this.起点 = 起点; }
public 路径区块[,] 导航权重绘制(导航区块 起点, 导航区块 终点, AI导航 请求者) { if (!终点) { #if 消息台 if (请求者.调试模式) { Debug.LogWarning("导航烘焙:参数错误):尝试修复>>1.检查目标是否越界或卡于障碍物中", 请求者); } #endif return(null); } //确定需复制的数据范围 int 长 = Mathf.Abs(终点.路径数据.x - 起点.路径数据.x) + 烘焙补偿; int 宽 = Mathf.Abs(终点.路径数据.y - 起点.路径数据.y) + 烘焙补偿; int 原点x = Mathf.Min(起点.路径数据.x, 终点.路径数据.x) - 烘焙补偿 / 2; int 原点y = Mathf.Min(起点.路径数据.y, 终点.路径数据.y) - 烘焙补偿 / 2; //防止烘焙补偿越界 #region 烘焙补偿优化 if (原点x < 0) { 长 += 原点x; 原点x = 0; } if (原点y < 0) { 宽 += 原点y; 原点y = 0; } int 超长 = 长 + 原点x + 1 - 烘焙数据.GetLength(0); if (超长 > 0) { 长 -= 超长; } int 超宽 = 宽 + 原点y + 1 - 烘焙数据.GetLength(1); if (超宽 > 0) { 宽 -= 超宽; } #endregion 路径区块[,] 路径数据 = new 路径区块[长, 宽]; for (int y = 宽 - 1; y >= 0; y--) { for (int x = 长 - 1; x >= 0; x--) { 路径数据[x, y] = new 路径区块(烘焙数据[x + 原点x, y + 原点y].路径数据); //复制导航烘焙数据 if (!路径数据[x, y].障碍物) { #if 可视化 if (请求者.调试模式) { if (x * y == 0 || x == 长 - 1 || y == 宽 - 1) { 烘焙数据[x + 原点x, y + 原点y].GetComponent <SpriteRenderer>().color = Color.yellow; } else { 烘焙数据[x + 原点x, y + 原点y].GetComponent <SpriteRenderer>().color = Color.white; } } #endif 路径数据[x, y].权重初始化(1, (烘焙数据[x + 原点x, y + 原点y].transform.position - 终点.transform.position).sqrMagnitude); //计算【路径区块】终点距离权重 } } } return(路径数据); }
public Stack <路径区块> 导航(路径区块 起点, 路径区块[,] 导航数据, AI导航 请求者) { if (起点 == null || 导航数据 == null) { #if 消息台 if (请求者.调试模式) { Debug.LogWarning("导航:参数错误):尝试修复>>1.检查AI是否越界或卡在障碍物中", 请求者); } #endif return(null); } List <路径区块> 开启列表 = new List <路径区块>(); List <路径区块> 关闭列表 = new List <路径区块>(); Stack <路径区块> 路径列表 = new Stack <路径区块>(); //栈结构便于正向输出路径 路径区块 当前路径点 = 起点; 当前路径点.起点距离 = 0; 开启列表.Add(当前路径点); while (开启列表.Count != 0) { 路径区块 临时路径点 = 当前路径点; 开启列表.Remove(当前路径点); 关闭列表.Add(当前路径点); List <路径区块> 周围路径 = 寻找周围路径(当前路径点, 关闭列表, 导航数据, 请求者); foreach (路径区块 路径点 in 周围路径) { float 距离 = 当前路径点 - 路径点; //计算【路径区块】起点距离权重 if (!开启列表.Contains(路径点)) { 路径点.一个路径点 = 当前路径点; 路径点.起点距离 = 当前路径点.起点距离 + 距离; 路径点.总距离 = 路径点.起点距离 + 路径点.终点距离; 开启列表.Add(路径点); } else if (路径点.起点距离 > 当前路径点.起点距离 + 距离) { 路径点.一个路径点 = 当前路径点; 路径点.起点距离 = 当前路径点.起点距离 + 距离; 路径点.总距离 = 路径点.起点距离 + 路径点.终点距离; } } 当前路径点 = 寻找最小终点距离(开启列表); //录入路径 if (当前路径点 == null) { #if 消息台 if (请求者.调试模式) { Debug.LogWarning("导航:无法获取最小路径):尝试修复>>1.检测【路径区块】距离权重值 2.检测是否无可走路径", 请求者); } #endif return(null); } if (当前路径点.终点距离 == 0) { do { #if 可视化 if (请求者.调试模式) { 导航烘焙.烘焙数据[当前路径点.x, 当前路径点.y].GetComponent <SpriteRenderer>().color = Color.blue; } #endif 路径列表.Push(当前路径点); 当前路径点 = 当前路径点.一个路径点; } while (当前路径点.一个路径点 != null); break; } } return(路径列表); }