寻路 - 超出界限的索引

时间:2016-11-26 15:31:13

标签: c# unity3d path-finding

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

问题出现在以下图像中:Works perfectly 1)在此镜头中,航点设置为(6,6)并且不返回任何错误。 Error 2)注意右上角的2个点,其中一个显示没有方向,另一个显示。错误是指向上方的节点。在这个镜头中,航点被移动到(7,5),此时它开始从最后一个索引开始抛出错误。我越靠近右下角移动航点越多,Y轴下X = 13的点越多,抛出异常。

相关代码:

Index out of Bounds

当我添加检查以查看朝向该方向的点是否可通过时,仅抛出此direction.y错误。另外需要注意的是,我使用Private Sub CommandButton1_Click() Dim Sel_Manager As String 'Headers repeated at the top Application.PrintCommunication = False With ActiveSheet.PageSetup .PrintTitleRows = "$2:$2" .PrintTitleColumns = "$B:$M" .Orientation = xlLandscape .Zoom = False .FitToPagesWide = 1 .FitToPagesTall = 1 End With 'Manager selection through ComboBox dropdown Sel_Manager = ComboBox1 'Inserting autofilters for worksheet Cells.Select Selection.AutoFilter 'Manager defined in the dropdown ComboBox ActiveSheet.Range("B2", Range("M2").End(xlDown)).AutoFilter Field:=1, Criteria1:=Sel_Manager ActiveSheet.Range("B2", Range("M2").End(xlDown)).AutoFilter Field:=2, Criteria1:="A" 'Here I select range to be printed and specify manager in filename ActiveSheet.Range("B2", Range("M2").End(xlDown)).Select Selection.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _ Sel_Manager + ".pdf", Quality:=xlQualityStandard, _ IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:=True ActiveSheet.ShowAllData Application.PrintCommunication = True End Sub ,其中方向实际存储在x和z中。出于某种原因,如果我使用z代替y,它将完全停止工作。

2 个答案:

答案 0 :(得分:3)

如有疑问,请尝试浏览测试用例,看看出了什么问题。

让我们说我们在第二张图片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偏移,它可能会更短,因为你在归零之前将其标准化。

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 *。

答案 1 :(得分:1)

Make a simple function that checks if you are within the bounds of the map.grid 2D array before doing if (map.grid[x + (int)direction.x, y + (int)direction.y].passable).

Check if map.grid[x + (int)direction.x is less than map.sizeX-1

then check if map.grid[ y + (int)direction.y] is less than map.sizeY-1.

If both conditions are met, go ahead with the if (map.grid[x + (int)direction.x, y + (int)direction.y].passable).

Here is a simple function to simplify that:

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));
}

Now you can just do:

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;
                        }
                    }
                }
            }
        }
    }
}