You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#实现游戏路径瓦片生成功能时while死循环无法退出如何解决

问题1:循环无法停止的原因
  • 最核心的错误是循环终止条件逻辑错误:你当前的while条件使用了||(逻辑或)连接三个判断,也就是说只要任意一个条件成立,循环就会继续运行。哪怕坐标已经到达B点,只要failSafe不等于50,循环就不会停止,必须等到failSafe累加到50才会触发终止,这就是你必须加故障安全才能停的根本原因。
  • 次要问题是浮点值等值比较风险:Vector2的x/y是float类型,受浮点精度误差影响,哪怕理论计算上坐标已经对齐,也可能因为小数点后微小的误差导致==判断不成立,循环永远不会满足坐标终止条件。
问题2:代码重复冗余的优化方案

你的实现本质是生成A到B的曼哈顿路径(横向+纵向走直角线),可以大幅简化逻辑,不需要写大量重复的方向判断:

  1. 先计算X/Y轴的移动步长,不用分别判断正负做加减
  2. 把坐标转成整数做比较,规避浮点精度问题
  3. 建议提前构建坐标 -> MapTile的字典映射,不用每次循环遍历全量瓦片列表,性能提升非常明显
  4. 修复循环条件逻辑,把逻辑或改成逻辑与,只有当未到终点且故障安全没触发时才继续循环
修复优化后的参考代码
// 提前初始化坐标映射字典,不用每次调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 12:27:04