大家好,我正在编写自己的寻路脚本,首先将其写在纸上,然后开始编码,然后让我告诉你,实践上比理论上难得多。因此,我遇到了一个问题,我当然无法解决。
问题出现在以下图像中: 1)在此镜头中,航路点设置为(6,6),并且不返回任何错误。
2)注意右上角的2个点,一个不显示方向,另一个显示。错误是指向上方的节点。在此镜头中,航路点移至(7,5),此点开始从最后一个索引开始引发错误。我将航路点移得越靠近右下角越多,则Y轴上X = 13处的点越多,则会引发异常。
相关代码:
for (int x = 0; x < map.sizeX; x++)
{
for (int y = 0; y < map.sizeY; y++)
{
if (!(x == pVal.x && y == pVal.y) && map.grid[x, y].passable )
{
float dot = 1;
var heading = (grid[x, y].position - t.position).normalized;
heading.y = 0;
foreach (Vector3 direction in map.GetDirections())
{
var dot2 = Vector3.Dot(heading, direction.normalized);
if (dot > dot2 )
{
if (map.grid[x + (int)direction.x, y + (int)direction.y].passable)
{ // Error thrown when it reaches this if-statement \\
grid[x, y].direction = direction;
dot = dot2;
}
}
}
}
}
}
仅当我添加检查以查看指向该方向的点是否可通过时,才会引发此
Index out of Bounds
错误。要注意的另一件事是,我使用direction.y
将方向实际存储在x和z中。由于某些原因,如果我使用z而不是y,它将完全停止工作。 最佳答案
如有疑问,请尝试遍历一个测试用例,看看有什么问题。
假设我们在第二张图片x = 13, y = 12
if (!(x == pVal.x && y == pVal.y) && map.grid[x, y].passable )
(13,12)不是我们的目标点,并且是可以通过的,因此我们通过了此测试,然后继续进行下一行...
float dot = 1;
var heading = (grid[x, y].position - t.position).normalized;
heading.y = 0;
heading
在这里最终类似于(0.659, 0, 0.753)
,尽管如果您有一些y偏移量,它可能会更短,因为您可以在将y归零之前对其进行归一化。foreach (Vector3 direction in map.GetDirections())
我不知道您的路线以什么顺序存储,所以我只在这里猜测:
{(0, 0, 1), (1, 0, 1), (1, 0, 0), (1, 0, -1)...}
以(0,0,1)开头,然后...
var dot2 = Vector3.Dot(heading, direction.normalized);
if (dot > dot2 )
dot
仍为1,并且dot2
为0.753,因此我们通过了此测试,请检查上方的单元格是否可通过(即使该点与我们要前进的方向完全相反!稍后将进一步介绍),设置并尝试下一个方向:(1、0、1)归一化为
dot = dot2
。 (0.707, 0, 0.707)
是0.753,dot
是0.466 + 0.532 = 0.998,因此我们在dot2
测试中失败并跳过了这一测试。这是杀手::(1、0、0)
dot > dot2
仍为0.753,dot
为0.659,因此我们通过了dot2
测试,并继续朝该方向检查单元格:if (map.grid[x + (int)direction.x, y + (int)direction.y].passable)
{ // Error thrown when it reaches this if-statement \\
没有开玩笑的错误!我们已经是
dot > dot2
(即at x = 13
),并且我们加了1,所以我们不在讨论区了!因此,仅通过遍历问题案例就很容易检测到此错误。
可能的修复(从最多到最小)
每当您尝试访问相邻的单元格时,请进行边界检查,如果会引出地图,请跳过边界。
在地图周围添加未使用的网格单元的边框,因此检查边缘的一个单元永远不会造成问题。
如果您要使用路径信息填充整个网格,请考虑改用更传统的,经过深入研究的寻路算法,例如广度优先搜索(所有移动的成本都相同)或Djikstra的算法(不同的移动成本),或者如果要为整个网格填充路径信息想要最短的点对点路径。
关于c# - 寻路-超出界限的索引,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40819930/