寻路 - 索引越界

问题描述:

好日子大家,我在写我自己的寻路的脚本,首先必须在纸上,然后开始编码,让我告诉你,这是在实践中更难比理论。所以,我遇到了一个问题,我当然无法解决。寻路 - 索引越界

的问题提出了自己在下面的图片:Works perfectly 1)在这幅图中,航点设置为(6,6),并返回没有错误。 Error 2)请注意,在右上角的2点,一个没有显示出方向上的另一显示出来。错误是指向上的节点。在这个镜头中,航点被移到(7,5),此时它开始从最后一个索引开始抛出错误。我越动航点接近右下角,在X = 13倒Y轴的多点抛出异常。

相关代码:

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,所以我们通过这个测试,检查上面的单元格尚可(即使该点远离疯狂从我们想要去的方向开始!更多关于很快),设置dot = dot2并尝试下一个方向:

(1,0,1)标准化到(0.707, 0, 0.707)dot是0.753,dot2是0.466 + 0.532 = 0.998所以我们不通过dot > dot2测试并跳过这一个。

这里的杀手锏:(1,0,0)

dot仍是0.753和dot2为0。659,所以我们通过dot > dot2测试,并进行检查电池在那个方向:

if (map.grid[x + (int)direction.x, y + (int)direction.y].passable) 
{ // Error thrown when it reaches this if-statement \\ 

别开玩笑抛出一个错误!我们已经是at x = 13(即map.sizeX - 1),我们加了1,所以我们离开了董事会的边缘!


所以,这个错误很容易仅仅通过问题的情况下行走探测。

可能修复(从多到少哈克):

  • 难道每当您尝试访问的相邻小区边界检查,并跳过它,如果它会导致从地图上。

  • 在地图周围添加未使用的网格单元的边框,因此从边缘检查一个单元格从不会造成问题。如果你想用路径信息填充整个网格,考虑切换到一个更传统的,研究得很好的寻路算法,如广度优先搜索(所有运算花费相同)或Djikstra算法(不同的移动成本)或A *如果你想要最短的点对点路径。

做一个简单的函数来检查,如果你是map.grid二维数组的做if (map.grid[x + (int)direction.x, y + (int)direction.y].passable)之前的范围内。

检查map.grid[x + (int)direction.x小于map.sizeX-1

然后检查map.grid[ y + (int)direction.y]小于map.sizeY-1

如果满足这两个条件,请继续执行if (map.grid[x + (int)direction.x, y + (int)direction.y].passable)

下面是一个简单的函数来简化:

bool isWithinBound(Vector3 direction, int sizeX, int sizeY, int x, int y) 
{ 
    return ((x + (int)direction.x < sizeX - 1) && (y + (int)direction.y < sizeY - 1)); 
} 

现在,你可以这样做:

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) 
       { 
        //Check if we are within bounds 
        if (isWithinBound(direction, map.sizeX, map.sizeY, x, y)) 
        { 
         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; 
         } 
        } 
       } 
      } 
     } 
    } 
}