private List <导航区块> 寻找周围路径(导航区块 路径点) { List <导航区块> 列表 = new List <导航区块>(); for (int i = 0; i < 4; i++) { 导航区块 临时路径点 = null; int x = 路径点.x; int y = 路径点.y; switch (i) { case 0: y++; break; case 1: x++; break; case 2: y--; break; case 3: x--; break; } try { 临时路径点 = 导航烘焙.数据[x, y].GetComponent <导航区块>(); if (!临时路径点.墙壁 && !关闭列表.Contains(临时路径点)) { 列表.Add(临时路径点); } } catch { continue; } } return(列表); }
IEnumerator 开始寻路() { WaitForSeconds s = new WaitForSeconds(0.03f); 最小路径点 = 导航烘焙.数据[起点x, 起点y].GetComponent <导航区块>(); 开启列表.Add(最小路径点); while (开启列表.Count != 0) { 导航区块 临时路径点 = 最小路径点; 开启列表.Remove(最小路径点); 关闭列表.Add(最小路径点); List <导航区块> 周围路径 = 寻找周围路径(最小路径点); foreach (导航区块 路径点 in 周围路径) { if (!开启列表.Contains(路径点)) { 路径点.一个路径点 = 最小路径点; 路径点.起点距离 = 最小路径点.起点距离 + 1; 路径点.总距离 = 路径点.起点距离 + 路径点.终点距离; 开启列表.Add(路径点); } else if (路径点.起点距离 > 最小路径点.起点距离 + 1) { 路径点.一个路径点 = 最小路径点; 路径点.起点距离 = 最小路径点.起点距离 + 1; 路径点.总距离 = 路径点.起点距离 + 路径点.终点距离; } } 最小路径点 = 寻找最小终点距离(开启列表); 导航烘焙.数据[临时路径点.x, 临时路径点.y].GetComponent <SpriteRenderer>().color = Color.yellow; yield return(s); 导航烘焙.数据[临时路径点.x, 临时路径点.y].GetComponent <SpriteRenderer>().color = Color.white; if (最小路径点.终点距离 == 0) { do { 导航烘焙.数据[最小路径点.x, 最小路径点.y].GetComponent <SpriteRenderer>().color = Color.blue; 最小路径点 = 最小路径点.一个路径点; yield return(s); } while (最小路径点.一个路径点 != null); break; } } 导航烘焙.数据[寻路.起点x, 寻路.起点y].GetComponent <SpriteRenderer>().color = Color.red; 导航烘焙.数据[寻路.终点x, 寻路.终点y].GetComponent <SpriteRenderer>().color = Color.green; }
private 导航区块 寻找最小终点距离(List <导航区块> 列表) { 导航区块 最小距离点 = null; int 最小距离 = int.MaxValue; foreach (导航区块 i in 列表) { if (i.总距离 < 最小距离) { 最小距离点 = i; 最小距离 = i.总距离; } } return(最小距离点); }
public 路径区块[,] 导航权重绘制(导航区块 起点, 导航区块 终点) { if (终点 == null) { #if 开启 Debug.LogWarning("导航权重绘制:无法获取导航区块数据"); #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; if (原点x < 0) { 长 += 原点x; 原点x = 0; } if (原点y < 0) { 宽 += 原点y; 原点y = 0; } int 超长 = 长 + 原点x - 烘焙数据.GetLength(0); if (超长 > 0) { 长 -= 超长; } int 超宽 = 宽 + 原点y - 烘焙数据.GetLength(1); if (超宽 > 0) { 宽 -= 超宽; } 路径区块[,] 路径数据 = new 路径区块[长, 宽]; for (int y = 宽 - 1; y >= 0; y--) { for (int x = 长 - 1; x >= 0; x--) { try { 路径数据[x, y] = new 路径区块(烘焙数据[x + 原点x, y + 原点y].路径数据); //复制导航烘焙数据 if (!路径数据[x, y].障碍物) { #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); } } catch { #if 开启 Debug.LogWarning("脱离烘焙区域"); return(null); #endif } } } return(路径数据); }
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(路径数据); }