寻路 - 索引越界
好日子大家,我在写我自己的寻路的脚本,首先必须在纸上,然后开始编码,让我告诉你,这是在实践中更难比理论。所以,我遇到了一个问题,我当然无法解决。寻路 - 索引越界
的问题提出了自己在下面的图片: 1)在这幅图中,航点设置为(6,6),并返回没有错误。
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;
}
}
}
}
}
}
}