深度有限搜索的寻径(Unity/ c# ~)
本文关键字:Unity 搜索 深度 | 更新日期: 2023-09-27 18:13:18
我正在制作一款基于网格的游戏,其中角色可以轮流移动他们的单位。每个角色都有一个移动量(例如4 -他们可以移动4个贴图)。我已经实现了一个DLS(它限制了它们的移动量)。使用这种方法,玩家可以移动到的所有可用贴图都会被高亮显示。
这很好。然而,我想修改算法(或实现一个特定的算法)来计算出路由。例如,玩家想要G3 -角色应该走什么路线(向前1,向左1等)。请记住,每个瓷砖可以有不同的属性(例如有些可能被阻塞)。
private void DLS(int x, int z, int depth, float jump, float previousHeight)
{
int resistance=1;
if (depth >=0)
{
tiles[x,z].GetComponentInChildren<CheckIfClicked>().Selected();
if (x+1 < 25)
{
CheckTile(x+1, z, depth, jump, previousHeight);
}
if (x-1 >= 0)
{
CheckTile(x-1, z, depth, jump, previousHeight);
}
if (z+1 <25)
{
CheckTile(x, z+1, depth, jump, previousHeight);
}
if (z-1 >=0)
{
CheckTile(x, z-1, depth,jump, previousHeight);
}
}
}
private void CheckTile(int x, int z, int depth, float jump, float previousHeight)
{
float tileHeight = tiles[x, z].GetComponent<TileDimensions>().height;
float difference = tileHeight - previousHeight;
if (difference<0) difference*=-1;
if (!tiles[x, z].GetComponentInChildren<CheckIfClicked>().occupied && difference<jump)
{
int resistance = tiles[x, z].GetComponent<TileDimensions>().getResistance();
if (resistance<0) resistance=1;
DLS(x, z, depth-resistance, jump, tileHeight);
}
}
我的代码利用了不同的贴图属性(比如贴图的阻力(有些贴图限制移动)和高度(你只能爬这么远))。
如果您希望使用更有效的算法,有两种建议的实现:
-
一个明星。当你知道你想去的目的地,但你需要找到到达那里的路时,最好使用星号。如果你点击了G3,而你在G1,你就知道你要去哪里了。星型算法利用启发式算法试图"猜测"。你还要走多远。这意味着当搜索可能的路线时,A星将尝试选择最短的路线,然后再尝试查看其他路线。这里有一个很棒的教程:Link
-
Djikstra的算法。当你不知道自己要去哪里,但你想要找到包含特定"东西"的最近节点时,这是最好的选择,例如,你可能希望你的人工智能在FPS中搜索最近的生命包。我以前没有实现过Djikstra的算法,但是网上有很多教程。
使用这两种方法,您可以添加属性,如某些瓷砖的阻力和其他任何属性
既然你的算法是工作的,我想给你一些建议来增强你的代码,都涉及使用列表/字典。
执行一次路径搜索
如果你可以突出显示每个可移动的贴图,这意味着你可以遍历从源贴图到不同目的地贴图的路径,这意味着你可以一个接一个地验证贴图,直到角色无法进行额外的移动。因此,您可以将结果存储到"目标tile - lists"对的字典中。当您需要检索到特定tile的路径时,只需获取先前存储的路径。
执行两次路径搜索
由于上述方法可能占用大量内存,所以你可以在玩家移动时再次运行路径搜索算法。第二次执行所花费的时间应该少于第一次,因为玩家已经指定了特定的贴图作为路径的目的地。在第二次搜索期间,继续更新列表/字典,同时递归地执行路径搜索函数。将每个有效的中间块保存到列表/字典中,然后您可以在搜索后获得路径。
如果你是在手机平台上开发游戏,那么即使是一点点的内存使用也很重要。我建议执行路径搜索的时间是玩家所能接受的时间的两倍。
当然,通过Unity Profiler来检查哪种方法更适合你的需求,始终是一个很好的实践。