大家好,我正在编写我自己的寻路脚本,首先将它写在纸上然后开始编码让我告诉你,它在实践中比理论上难得多。所以,我遇到了一个问题,我当然无法解决。
问题出现在以下图像中: 1)在此镜头中,航点设置为(6,6)并且不返回任何错误。 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,它将完全停止工作。
答案 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;
}
}
}
}
}
}
}