Unity3D架构设计NavMesh寻路

Unity3D架构设计NavMesh寻路

国庆闲来没事把NavMesh巩固一下。以Unity3D引擎为例写一个底层c# NavMesh寻路。因为Unity3D中本身自带的NavMesh寻路不能很好的融入到游戏项目当中,所以重写一个NavMesh寻路是个必经之路。NavMesh在很多游戏中应用广泛,不同种类的框架下NavMesh寻路发挥的淋漓尽致。与传统的A星寻路相比,NavMesh不仅减少了内存空间占有量,加快了寻路速度,还可以加入寻路角色的宽高限制,以及动态物体寻路等功能,基本上适应了大部分项目变化多端的需求。

我把写NavMesh的过程分成好几个部分,一一进行描述:

一.首先要理解NavMesh核心算法。NavMesh的核心算法就是用三角形代替传统寻路的方格,用计算拐点优化寻路路径来代替合并路径直线。

如下图1NavMesh寻路:

Unity3D架构设计NavMesh寻路

以及如下图2传统的方格寻路:

Unity3D架构设计NavMesh寻路

看到两者的差别了吧,NavMesh已三角形为寻路块,而传统以方格为寻路块。其实两者都使用A*寻路,但就是其网格生成不一样,导致当有大范围寻路时,其效率和要求也不一样。

二.NavMesh寻路中的路径优化之拐点计算。其实NavMesh中比较常用的是光照射线法,但这里不做详细介绍,光照射浅法详细内容地址:http://www.cnblogs.com/neoragex2002/archive/2007/09/09/887556.html

拐点计算优化路径就是到达目的地需要经过的一堆三角形中计算出最简洁的移动方式。其核心算法就是从当前点到另一个三角形中的点之间的线段,与这条线段相交的线段全部是路径所穿越的线段,就是拐点,把所有的拐点找出来,并得到一条最长的拐点,那个拐点就是最佳的拐点位置。

三.NavMesh类设计详解(这里只设计2D的寻路,对于3D方向的寻路,其实是可以2D寻路代替的):

1.所有类都在同一的命名空间NavMesh内 namespace NavMesh

Triangle 三角形基础类

NavTriangle 寻路三角形类 (继承Triangle)

Line2D 线段类

Polygon 多边形类

Seeker 寻路主算法类

—————————————– 让大家久等了 ————————————

在寻路前,我们需要建立MESH三角形网格,这是NAV_MESH的重点之一。

1.首先我们先要画出一个范围来确定我们的可行走范围。

2.再在可行走范围中去添加不可行走的范围。

3.我们用多个多边形Polygon代替以上的范围,也就是说,一个大的可行走Polygon内包含了若干个小的不可行走的Polygon。

这是生成MESH前我们需要知道的生成范围,然后再由这些多边形的各个顶点来生成三角形网格,三角形网格的生成算法如下:

Step 1 :  用可行走Polygon的任意一条边作为起点,将其推入堆栈列表。到Step2.

Step 2:  从堆栈中推出一条边,在所有三角形中计算出边的DT点,构成约束Delaunay三角形,到Step3。如果没有DT点就重复做Step2,直到堆栈为空就结束整个程序。

Step 3:  将所构成的三角形,另两边做如下处理:检查堆栈中是否已存在,如果存在就删除该边,如果不存在就加入到堆栈中。

生成mesh后如图:(绿色的为多边形边框,蓝色的为寻路路径,红色的为编辑器选中的多边形)

Unity3D架构设计NavMesh寻路

核心源码为:

这里对如何计算DT点进行一个说明:

Step1. 构造三角形的外接圆,以及外接圆的包围盒
Step2. 依次访问网格包围盒内的每个网格单元:
若某个网格单元中存在可见点 p, 并且 ∠p1pp2 > ∠p1p3p2,则令 p3=p,转Step1;
否则,转Step3.
Step3. 若当前网格包围盒内所有网格单元都已被处理完,也即C(p1,p2,p3)内无可见点,则 p3 为的 p1p2 的 DT 点
核心源码为:

为了让各位能更容易读懂此文,此文仍会继续补充。现在我将所有源码都存放在了Github上,请各位跟随我到Github去取源码:https://github.com/luzexi/Unity3DNavMesh

转载请注明出处:http://www.luzexi.com

上一篇:spring security使用数据库管理用户权限


下一篇:ES6特性:(阮一峰老师)学习总结