Unity3D 2D游戏中寻径算法的一些解决思路

时间:2023-03-09 03:26:37
Unity3D 2D游戏中寻径算法的一些解决思路

需求

unity3d的3d开发环境中,原生自带了Navigation的组件,可以很便捷快速的实现寻路功能。但是在原生的2d中并没有相同的功能。

现在国内很多手机游戏都有自动寻路的功能,或者游戏中存在一些例如机器人、npc等,都需要自动寻路的功能。

我需要实现的功能类似于当年FC游戏中淘金者的运动方式。游戏中有淘金者、敌人,可移动,不可移动区域,只能沿着直线的向前向后或者向上向下。

Unity3D 2D游戏中寻径算法的一些解决思路

思路

unity3d中也有一些2d寻路的插件。例如A Pathfinding Project Pro和NavMesh 2D。

两个插件都是收费插件,可以满足不同需求,但是我用过之后发现并不是我想要的效果,而且修改别人的代码的还是挺难受的。所以决定自己写一遍A*算法。

A*算法已经有很多大牛的博客中,都有非常不错的介绍。我看的是这篇,给大家推荐下:传送

这篇文章的代码在于拐点的处理上是有一定问题的,我在下面的代码中有进行修改。

解决方案

先上结果,实现后的路径是这样的。请忽略那只乱入恐龙,他其实只是来打酱油的~~

Unity3D 2D游戏中寻径算法的一些解决思路

核心代码如下:

 public Point FindPath (Point start, Point end, bool IsIgnoreCorner)
{
OpenList.Add (start);
while (OpenList.Count != ) {
//找出F值最小的点
var tempStart = OpenList.MinPoint ();
OpenList.RemoveAt ();
CloseList.Add (tempStart);
//找出它相邻的点
var surroundPoints = SurrroundPoints (tempStart, IsIgnoreCorner);
foreach (Point point in surroundPoints) {
if (OpenList.Exists (point))
//计算G值, 如果比原来的大, 就什么都不做, 否则设置它的父节点为当前点,并更新G和F
FoundPoint (tempStart, point);
else
//如果它们不在开始列表里, 就加入, 并设置父节点,并计算GHF
NotFoundPoint (tempStart, end, point);
}
if (OpenList.Get (end) != null)
return OpenList.Get (end);
}
return OpenList.Get (end);
}

原文中有些小问题的CanReach方向,我修改的如下:

 public bool CanReach (Point start, int x, int y, bool IsIgnoreCorner)
{
if (!CanReach (x, y) || CloseList.Exists (x, y))
return false;
else {
if (Math.Abs (x - start.X) + Math.Abs (y - start.Y) == )
return true;
//如果是斜方向移动, 判断是否 "拌脚"
else {
if (IsIgnoreCorner) {
if (CanReach (Math.Abs (x - ), y) && CanReach (x, Math.Abs (y - )))
return true;
else
return false;
} else
return false;
}
}
}

总结

算法还是要多自己写一些,总是拿来主义不利于自己的成长,在大学里学过了,基本都还给老师了,项目里的东西,要用也要明明白白的用,防止为以后的开发留下隐患,到时候从头再找就需要话费给多的时间了。

项目源代码中包含了spine的例子,所以有点大,有兴趣的朋友可以下载去玩一玩。

点击下载源代码