如何修改现有A*算法以禁止特定场景下的斜向移动
修改PathFinderFast.cs以禁止障碍物间斜向穿行的方案
核心思路
保留原八向移动的高效逻辑,仅在生成斜向邻居节点时增加校验:当斜向移动的两个正交相邻格子均为障碍物时,禁止该斜向移动;其余斜向情况(沿障碍物单侧、开阔区域)仍允许。
具体修改步骤
定位邻居节点生成逻辑
找到原代码中遍历八向邻居的循环(通常是包含8个方向偏移的数组遍历,比如mDirectionOffsets类变量),在生成每个邻居节点前添加判断逻辑。添加斜向移动校验逻辑
对于每个待检查的邻居节点:
- 判断是否为斜向移动(即x和y方向的偏移量都不为0,比如偏移量是(1,1)、(1,-1)等)
- 如果是斜向移动,获取该斜向位置对应的两个正交相邻格子(比如目标位置是(x+1,y+1),则检查(x+1,y)和(x,y+1))
- 调用原代码中判断格子是否可行走的方法(比如
IsWalkable或直接读取网格状态),若两个正交格子均为障碍物,则跳过该斜向邻居节点;否则正常加入邻居列表。
- 代码示例(适配原PathFinderFast.cs结构)
假设原代码中方向偏移数组定义如下:
private static readonly Point[] mDirectionOffsets = new Point[] { new Point(0, -1), // 上 new Point(1, -1), // 右上 new Point(1, 0), // 右 new Point(1, 1), // 右下 new Point(0, 1), // 下 new Point(-1, 1), // 左下 new Point(-1, 0), // 左 new Point(-1, -1) // 左上 };
在遍历偏移生成邻居的代码块中,插入校验逻辑:
foreach (var offset in mDirectionOffsets) { int neighborX = currentX + offset.X; int neighborY = currentY + offset.Y; // 原有的边界与可行走校验 if (neighborX < 0 || neighborX >= mGridWidth || neighborY < 0 || neighborY >= mGridHeight) continue; if (!IsWalkable(neighborX, neighborY)) continue; // 新增斜向移动合法性校验 bool isDiagonalMove = offset.X != 0 && offset.Y != 0; if (isDiagonalMove) { // 获取两个正交相邻格子坐标 int orthoX1 = currentX + offset.X; int orthoY1 = currentY; int orthoX2 = currentX; int orthoY2 = currentY + offset.Y; // 若两个正交格子均为障碍物,禁止该斜向移动 bool bothOrthoBlocked = !IsWalkable(orthoX1, orthoY1) && !IsWalkable(orthoX2, orthoY2); if (bothOrthoBlocked) continue; } // 保留原代码中加入邻居列表、计算代价等逻辑 // ... }
- 验证场景
测试两种核心场景:
- 开阔区域:八向移动正常,斜向路径不受影响
- 相邻障碍物夹缝:斜向穿行被禁止,路径自动绕开或沿单侧障碍物移动
注意事项
- 确保
IsWalkable是原代码中判断格子通行状态的正确方法,若原代码直接通过数组索引判断(如mGrid[neighborX, neighborY]),替换为对应逻辑即可 - 无需修改
mDiagonals字段,该字段用于控制是否开启八向移动,我们需要保留八向能力,仅过滤非法斜向情况
内容的提问来源于stack exchange,提问作者Kidd
相关产品推荐
相关产品推荐

