【发布时间】:2019-04-28 23:09:07
【问题描述】:
我有我的 NPC,我有一个目标位置给他。我已将我的 A* 寻路算法放入代码中。这创造了一条道路,但它绝不是一条理想的道路,也没有凝聚力。我已经写了几次这篇文章,发现自己面临同样的问题。
这张图应该显示我的问题的结果:最终路径到处都是。
对我来说,算法似乎是在我的地图上的每个图块之间寻找连接,而不是找到最佳路径。不过,我真的无法确定这是在哪里发生的。
为了清楚起见,我在加载我的游戏场景时定义了图块(正方形)及其邻居。当程序到达 GetAdjacentSquares 时,它正在使用这些结果来查找有效的图块。你会注意到他们 NPC 的路径并没有直接以任何绿色瓷砖为中心。
List<Path> GetAdjacentSquares(Path p)
{
List<Path> ret = new List<Path>();
TileData tile = tManager.GetTileByCoords(new Vector2(p.x, p.y));
foreach (Vector2 t in tile.neighborLocs)
{
TileData n = tManager.GetTileByCoords(t);
if (n && n.tType == TileTypes.Houses || n.tType == TileTypes.Road)
{
ret.Add(new Path(p, n.tTileLoc.x, n.tTileLoc.y));
}
}
return ret;
}
int BlocksToTarget(Vector2 tileLoc, Vector2 targetLoc)
{
int final = (int)Mathf.Abs((tileLoc.x - targetLoc.x) * (tileLoc.x - targetLoc.x) + (tileLoc.y - targetLoc.y) * (tileLoc.y - targetLoc.y));
return final;`
}
bool DoesPathContain(List<Path> paths, Vector2 target)
{
foreach(Path p in paths)
{
if (p.x == target.x && p.y == target.y)
return true;
}
return false;
}
int LowestFScore(List<Path> path)
{
int lowest = int.MaxValue;
foreach(Path p in path)
{
if (p.f <= lowest)
lowest = p.f;
}
return lowest;
}
void GoHome()
{
Path current = null;
//target
Path destination = new Path(null, cData.houseLoc.x, cData.houseLoc.y);
//start
Path start = new Path(destination, transform.localPosition.x, transform.localPosition.y);
//start by adding the original position to the open list
List<Path> open = new List<Path>() { start };
List<Path> close = new List<Path>();
int g = 0;
while(open.Count > 0)
{
//get the square with the lowest F score
current = open.Last(p => p.f == LowestFScore(open));
//add the current square to the closed list
close.Add(current);
//remove it from the open list
open.Remove(current);
//if we added the destination to the closed list, we've found a path
if(DoesPathContain(close, cData.houseLoc))
break;
//The rest of the algorithm evaluates adjacent tiles
List<Path> adjacentTiles = GetAdjacentSquares(current);
g++;
foreach(Path tile in adjacentTiles)
{
Vector2 tileLoc = new Vector2(tile.x, tile.y);
//if this adjacent square is already in the closed list, ignore it
if (DoesPathContain(close, tileLoc))
continue;
if(!DoesPathContain(open, tileLoc))
{
//if this adjacent square is already in the closed list, ignore it
tile.g = g;
tile.h = BlocksToTarget(tileLoc, cData.houseLoc);
tile.parent = current;
//add it to the open list
open.Add(tile);
}
else
{
//test if using the current G score makes the adjacent square's F score
//lower, if yes update the parent because it means it's a better path
if (g+tile.h < tile.f)
{
tile.g = g;
tile.parent = current;
}
}
}
}
//foreach (Path p in close)
// Debug.Log(p.f + " ("+p.x+", "+p.y+")");
walkTo = close;
cData.isWalking = true;
}
`
【问题讨论】:
-
您链接的图像似乎已损坏。您介意验证链接吗?
-
就是这样!我不得不尝试在 Dropbox 和 Imgur 上发布这个东西。在我从个人资料设置中加载图像之前,Imgur 的共享链接无法使用。
-
好多了。乍一看让我觉得你的公式寻找的是最长的路径而不是最短的......检查你的
<和>s 也许? -
你能解释一下你的形象吗?起点是什么,目标又是什么?不同颜色的线条是什么意思?
-
我用A*已经有一段时间了,但是你不是要每一步都更新F-score(即
tile.f = g+h)吗? (编辑:稍作修改)
标签: c# unity3d path-finding