C#实现游戏路径瓦片生成功能时while死循环无法退出如何解决
问题1:循环无法停止的原因
- 最核心的错误是循环终止条件逻辑错误:你当前的while条件使用了
||(逻辑或)连接三个判断,也就是说只要任意一个条件成立,循环就会继续运行。哪怕坐标已经到达B点,只要failSafe不等于50,循环就不会停止,必须等到failSafe累加到50才会触发终止,这就是你必须加故障安全才能停的根本原因。 - 次要问题是浮点值等值比较风险:
Vector2的x/y是float类型,受浮点精度误差影响,哪怕理论计算上坐标已经对齐,也可能因为小数点后微小的误差导致==判断不成立,循环永远不会满足坐标终止条件。
问题2:代码重复冗余的优化方案
你的实现本质是生成A到B的曼哈顿路径(横向+纵向走直角线),可以大幅简化逻辑,不需要写大量重复的方向判断:
- 先计算X/Y轴的移动步长,不用分别判断正负做加减
- 把坐标转成整数做比较,规避浮点精度问题
- 建议提前构建
坐标 -> MapTile的字典映射,不用每次循环遍历全量瓦片列表,性能提升非常明显 - 修复循环条件逻辑,把逻辑或改成逻辑与,只有当未到终点且故障安全没触发时才继续循环
修复优化后的参考代码
// 提前初始化坐标映射字典,不用每次调用RoadBuilder都遍历 private Dictionary<Vector2Int, MapTile> _tilePosMap; // 初始化时执行一次即可 private void InitTileMap() { _tilePosMap = new Dictionary<Vector2Int, MapTile>(); foreach (var tile in _mapList) { var pos = new Vector2Int(Mathf.RoundToInt(tile.position.x), Mathf.RoundToInt(tile.position.y)); _tilePosMap[pos] = tile; } } private void RoadBuilder(Vector2 pointA, Vector2 pointB, Image pathTile) { // 转成整数坐标规避浮点误差 Vector2Int a = new Vector2Int(Mathf.RoundToInt(pointA.x), Mathf.RoundToInt(pointA.y)); Vector2Int b = new Vector2Int(Mathf.RoundToInt(pointB.x), Mathf.RoundToInt(pointB.y)); int currentX = a.x; int currentY = a.y; // 计算步长:正数+1,负数-1,0就不动 int stepX = (int)Mathf.Sign(b.x - a.x); int stepY = (int)Mathf.Sign(b.y - a.y); int failSafe = 0; const int maxFailSafe = 100; // 修复循环条件:未到终点 且 没触发故障安全才继续 while ((currentX != b.x || currentY != b.y) && failSafe < maxFailSafe) { // 先走完X轴再走Y轴,也可以保留你之前的交替走逻辑,代码一样简洁 if (currentX != b.x) { currentX += stepX; } else if (currentY != b.y) { currentY += stepY; } // 直接查字典找瓦片,不用遍历全列表 var currentPos = new Vector2Int(currentX, currentY); if (_tilePosMap.TryGetValue(currentPos, out var tempTile) && tempTile.tileSprite != _tiles[1] && tempTile.tileSprite != _tiles[4] && currentPos != b) { tempTile.tileSprite = pathTile; } failSafe++; } }
内容的提问来源于stack exchange,提问作者Chris Luna
相关产品推荐
相关产品推荐

