大家好,我正在编写自己的寻路脚本,首先将其写在纸上,然后开始编码,然后让我告诉你,实践上比理论上难得多。因此,我遇到了一个问题,我当然无法解决。

问题出现在以下图像中:c# - 寻路-超出界限的索引-LMLPHP 1)在此镜头中,航路点设置为(6,6),并且不返回任何错误。
c# - 寻路-超出界限的索引-LMLPHP 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/

10-10 17:06