需求

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

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

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

unity3d寻路高性能 unity3d寻路算法_unity3d寻路高性能

 

思路

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

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

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

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

解决方案

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

unity3d寻路高性能 unity3d寻路算法_3d_02

核心代码如下:

1 public Point FindPath (Point start, Point end, bool IsIgnoreCorner)
 2     {
 3         OpenList.Add (start);
 4         while (OpenList.Count != 0) {
 5             //找出F值最小的点
 6             var tempStart = OpenList.MinPoint ();
 7             OpenList.RemoveAt (0);
 8             CloseList.Add (tempStart);
 9             //找出它相邻的点
10             var surroundPoints = SurrroundPoints (tempStart, IsIgnoreCorner);
11             foreach (Point point in surroundPoints) {
12                 if (OpenList.Exists (point))
13                         //计算G值, 如果比原来的大, 就什么都不做, 否则设置它的父节点为当前点,并更新G和F
14                     FoundPoint (tempStart, point);
15                 else
16                         //如果它们不在开始列表里, 就加入, 并设置父节点,并计算GHF
17                     NotFoundPoint (tempStart, end, point);
18             }
19             if (OpenList.Get (end) != null)
20                 return OpenList.Get (end);
21         }
22         return OpenList.Get (end);
23     }

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

1 public bool CanReach (Point start, int x, int y, bool IsIgnoreCorner)
 2     {
 3         if (!CanReach (x, y) || CloseList.Exists (x, y))
 4             return false;
 5         else {
 6             if (Math.Abs (x - start.X) + Math.Abs (y - start.Y) == 1)
 7                 return true;
 8                 //如果是斜方向移动, 判断是否 "拌脚"
 9                 else {
10                 if (IsIgnoreCorner) {
11                     if (CanReach (Math.Abs (x - 1), y) && CanReach (x, Math.Abs (y - 1)))
12                         return true;
13                     else
14                         return false;
15                 } else
16                     return false;
17             }
18         }
19     }

总结

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

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

点击下载源代码