unity自带寻路Navmesh入门教程

来源:互联网 发布:红警网络进不去 编辑:程序博客网 时间:2024/04/25 05:10

http://liweizhaolili.blog.163.com/blog/static/16230744201271161310135/

unity自带寻路Navmesh入门教程(一) - 阿赵 - 有爪的小羔羊阿赵

 

      unity自从3.5版本之后,增加了NavMesh寻路的功能。在此之前,unity用户只能通过第三方插件(如Astar寻路插件)等做寻路功能。阿赵我也使用过A*寻路插件,A*的原理并不复杂,有兴趣的朋友可以自己百度一下。不过由于不是自带的功能,所以在设定网格和烘焙的过程难免会出现很多不便。NavMesh作为unity自带的功能,用法和之前的LightMapping烘焙或者遮挡剔除Occlusion Culling有很多相似之处。

      这个功能有很多有趣的地方,而且用起来也很方便,我打算分开几篇日志来逐一介绍。这次的目的只是简单的认识一下NavMesh的基本用法,所以暂时不详细的翻译组件每一个参数和功能的意思。

      先来看看怎么在unity打开NavMesh功能的窗口吧:

在window下拉列表中可以看到Navgation,点击:

unity自带寻路Navmesh入门教程(一) - 阿赵 - 有爪的小羔羊阿赵
在原来Inspector面板的旁边会出现Navigation的面板:
unity自带寻路Navmesh入门教程(一) - 阿赵 - 有爪的小羔羊阿赵
这个Objcet的面板是对应当前选择的物体的,旁边的Bake面板是对应全局选项的。结构和烘焙或者遮挡剔除是一样的。在选择了物体的情况下会出现上面的内容:
 上面的All、MeshRenderers、Terranis是对Hirarchy面板里面显示的物品选择的一个筛选过滤:
all就是全部显示
MeshRenderers是只显示可渲染的网格物体
而Terrains当然就是只显示地形物体了。
 
下面的是重要的选项,第一个Navigation Static选项是选择该物体是否用做寻路功能的一部分。只有勾选了这个选项,下面的其他选项才会可操作。
unity自带寻路Navmesh入门教程(一) - 阿赵 - 有爪的小羔羊阿赵
 OffMeshLink Generation选项是选择该物体是否根据高度、可跳跃宽带等全局的选项自动生成OffMeshLink,这个会在以后的讲解中详细说明,这次就暂时不讨论。
Navigation Layer是对参与寻路功能的地图物体的一个分类,用层来分类,默认有三个层可以选择,当然也可以自己添加层。
在Edit下拉列表,选择Project——NavMeshLayers
unity自带寻路Navmesh入门教程(一) - 阿赵 - 有爪的小羔羊阿赵
出现了NavMesh层的管理界面: 
unity自带寻路Navmesh入门教程(一) - 阿赵 - 有爪的小羔羊阿赵
上面三个Buit-in Layer是系统默认的三个可选择层,我们可以在下面的User Layer里面输入自己需要的层的名称,比如我现在输入一个叫做“brigde”的层
 
unity自带寻路Navmesh入门教程(一) - 阿赵 - 有爪的小羔羊阿赵
这时候,刚才输入的“bridge”层,就会出现在可选择的列表里面
 
通过刚才的几步,NavMesh常用的几个面板我们都已经操作过了,接下来可以做一个小例子:
unity自带寻路Navmesh入门教程(一) - 阿赵 - 有爪的小羔羊阿赵
 在场景里面,我放了一个摄像机(Camera),一个充当地面的面片(plane),一个角色模型(man)和一个目标点物体(target)
为了便于观察目标点的位置,我在目标点物体身上添加了Light组件让它会发光。角色模型(man)身上必须添加NavMesh组件,不然就不能寻路了。为了方便,我使用了官方的大兵模型,里面已经带有了动画和动画控制的脚本。不过这些动画的表现暂时是不重要的,你可以选择放一个胶囊或者Cube代替人物的模型。
 
unity自带寻路Navmesh入门教程(一) - 阿赵 - 有爪的小羔羊阿赵
还记得刚开始介绍的Navigation面板吗?选择地面(plane),在Navigation面板里面里面勾选Navigation Static选项,其他的默认不改动。
然后点击右下角的Bake面板。这时候会有一个计算的过程,曾经用过烘焙或者遮挡剔除的朋友应该对这个过程很熟悉了。
不过和之前两个功能一样,如果你没有保存场景level,unity会提示你先保存,然后再bake。
由于现在场景里面的物体很少,所以Bake的过程很快就结束了。
unity自带寻路Navmesh入门教程(一) - 阿赵 - 有爪的小羔羊阿赵
留意看scene视窗,现在地面的颜色已经发生改变了,这是因为unity已经帮你生成了寻路用的NavMesh网格,由于现在没有遮挡的阻碍物,所以整个地面都是属于可以行走的范围。
unity自带寻路Navmesh入门教程(一) - 阿赵 - 有爪的小羔羊阿赵
写一个最简单的控制脚本吧,以上是C#,由于很简单,估计用Js的朋友也能对应的写出来。
简单的解释一下,这个脚本是直接拖放到角色(man)身上的,并把场景中的目标物体(target)拖放指定到该脚本的target变量上面进行了赋值。在脚本一开始的时候,我 先获取了man身上的NavMeshAgent脚本组件,然后在Update的过程中,man不断的进行对target的位移的一个寻路并移动到目标位置的操作。
 
在进行完以上的操作后,你应该已经可以点击unity的播放按钮,然后移动目标物体(target),这时候角色模型已经可以追着目标点跑了。
这里我还做了一个简单的鼠标点击plane设定目标点的功能,由于这个功能不在这次的讨论范围内,所以有兴趣的朋友可以自己去百度一下具体的方法。
unity自带寻路Navmesh入门教程(一) - 阿赵 - 有爪的小羔羊阿赵
 
进行到这一步,人物已经跑起来了,但由于没有遮挡的障碍物,所以人物只是会直线的行走,看不出寻路的感觉。接下来我们就做点更复杂的:
unity自带寻路Navmesh入门教程(一) - 阿赵 - 有爪的小羔羊阿赵
在场景里面添加一个Cube做为障碍物,具体的形状和位置请根据自己喜欢来调节,阿赵我是把它做成了一个长方形,并摆在了角色面前。
unity自带寻路Navmesh入门教程(一) - 阿赵 - 有爪的小羔羊阿赵
和刚才对地面的操作差不多,选择遮挡物Cube,在Navigation面板里面勾选Navigation Static选项,这次的Navigation Layer要选择Not Walkable。顾名思义,这是不能行走的意思,代表了这个Cube是不能通过的。
选择完成后,我们再次点击Bake,又是一个小等待的过程。
Bake完成后,我们回到scene视窗。
unity自带寻路Navmesh入门教程(一) - 阿赵 - 有爪的小羔羊阿赵
 观察scene视窗,会发现刚才整个地面都是NavMesh的情况已经改变了,在障碍物的周围,NavMesh留出了一个缺口,这代表了角色已经不能从障碍物身上通过了。
 
再次点击unity的播放按钮
unity自带寻路Navmesh入门教程(一) - 阿赵 - 有爪的小羔羊阿赵
现在可以看到,人物已经可以绕着障碍物走了,我们的目的已经顺利达到了。
 
 
      这次的例子就到此结束了。
      在第二节里,我会详细的讲解高低落差、爬梯子以及跳跃等较为复杂一点的功能。然后会在第三节里面讲解分条件的寻路(不同人走不同的路),以及动态控制道路(如吊桥)等的功能。
      第一次写教程,可能有些不太人性化的地方,请各位谅解。
      再次提醒,请体谅作者辛苦,如需转载,请通知我,我是阿赵,谢谢!


     上一节简单介绍了NavMesh寻路的基本用法,这次来介绍一下稍微复杂一点点的高低落差以及跳跃的做法,首先来看看这次的目标:

unity自带寻路Navmesh入门教程(二) - 阿赵 - 有爪的小羔羊阿赵 
unity自带寻路Navmesh入门教程(二) - 阿赵 - 有爪的小羔羊阿赵

 由于博客相册上传GIF有限制,所以我把整个过程切开了2部分上传,第一部分是爬楼梯,第二部分是横向跳跃和往下跳落

      不管是爬楼梯,还是跳跃,NavMesh都是通过了OffMeshLink来做的。创建OffMeshLink的方法有两种,接下来会通过制作上面的例子来进行说明:

unity自带寻路Navmesh入门教程(二) - 阿赵 - 有爪的小羔羊阿赵
为了做这个例子,我们预先在场景里面准备了一些物体:摄像机是必须的,一个作为地面的Plane,然后是F1——F5几个高低落差不一样的台阶,L1和L2是楼梯模型, 控制人物主体man,还有移动的目标点target。
其中man身上必须带有NavMesh Agent组件,为了观察方便在target身上带了light组件。
 
unity自带寻路Navmesh入门教程(二) - 阿赵 - 有爪的小羔羊阿赵

 按照上一节所讲的,plane和F1——F5台阶在Navigation面板勾选Navigation Static选项,然后Bake,观察Scene视窗,会发现已经生成了我们所要的NavMesh网格,现在我们可以像上一节那样在plane上面给人物做寻路和移动了,但人物是不会爬楼梯的。

 

这时候,我们找到L1楼梯,在楼梯的开始和结束的位置放置两个点,这两个点只需要拾取它的位移的,你可以用empty Gameobject来做,我这里为了便于观察,就拿了cube来做。开始点命名为startPoint,结束点命名为endPoint。

unity自带寻路Navmesh入门教程(二) - 阿赵 - 有爪的小羔羊阿赵

 注意:startPoint和endPoint的位置要稍微比所在的平面高一点点。

 

接下来介绍第一种生成OffMeshLink的方法。选择L1楼梯,然后在Component下拉选项中选择Navigation——Off Mesh Link。

unity自带寻路Navmesh入门教程(二) - 阿赵 - 有爪的小羔羊阿赵

 

选择后,OffMeshLink组件已经添加到了L1的身上,我们可以在Inspector面板看到:

unity自带寻路Navmesh入门教程(二) - 阿赵 - 有爪的小羔羊阿赵

我们把刚才放置在场景里面的startPoint和endPoint指定到OffmeshLink组件的Start和End位置,其他选项默认不改变 

 

再次Bake

unity自带寻路Navmesh入门教程(二) - 阿赵 - 有爪的小羔羊阿赵

 

unity自带寻路Navmesh入门教程(二) - 阿赵 - 有爪的小羔羊阿赵

 现在我们发现,在scene面板里面,在startPoint和endPoint之间生成了一条线,而方向是从startPoint指向endPoint的。

 

unity自带寻路Navmesh入门教程(二) - 阿赵 - 有爪的小羔羊阿赵

 这时候,你应该可以通过移动目标点让角色开始爬楼梯了。但爬上去之后角色暂时不能跳下来,如果把目标点移动到plane上,角色会顺着楼梯爬下来。

我们使用同样的方法对L2进行生成OffMeshLink。这时候,角色应该可以爬两层楼梯了。到此第一个目标完成了。

 

接下来我们进行第二个目标的制作,首先先来分析一下我们的场景:

unity自带寻路Navmesh入门教程(二) - 阿赵 - 有爪的小羔羊阿赵

 我们希望人物能从2.5M的高度往下跳,超过2.5M人物就不能跳了,太高会有危险。然后横向我们希望人物能跳过2米的沟。

根据这个设定,我们的场景会是这样的情况:L1和L2只能通过爬楼梯,L2和L3之间可以跳跃,L3——L5是可以往下跳的。

 

于是,我们在Navigation面板里面找到Bake栏,Drop Height(掉落高度)填2.5,Jump Distance(跳跃距离)填2,单位都是米

unity自带寻路Navmesh入门教程(二) - 阿赵 - 有爪的小羔羊阿赵

 

接下来介绍第二种生成OffMeshLink的方法:

我们把L1——L5的物体选中,在Navigation面板的Object栏里面把OffMeshLink Generation选项打上勾

unity自带寻路Navmesh入门教程(二) - 阿赵 - 有爪的小羔羊阿赵

 

再次Bake,回到scene视窗:

unity自带寻路Navmesh入门教程(二) - 阿赵 - 有爪的小羔羊阿赵

这时候,场景里面会出现很多心的OffMeshLink,这是unity通过计算,把可以跳跃或者下落的地方自动生成了OffMeshLink了。

这时候,你应该已经可以通过移动目标点,让角色进行跳跃和下落了。 

 

进行到这里,我们的第二个目标也完成了。

 

不过有些朋友可能会提出疑问,在做的过程中,假如没有这个大兵的模型,而是用一个胶囊体来代替人物的话,它爬楼梯和跳跃的时候好像是在一瞬间完成的,没有大兵那个爬楼梯和跳跃动作的过程。如这样:

unity自带寻路Navmesh入门教程(二) - 阿赵 - 有爪的小羔羊阿赵 
unity自带寻路Navmesh入门教程(二) - 阿赵 - 有爪的小羔羊阿赵
的确是这样,因为默认的NaveMesh Agent组件上面是勾选了Auto Traverse Off Mesh Link(自动通过OffMeshLink)选项的。这样的意思是人物只要到了OffMeshLink的开始点,就会自动的移动到OffMeshLink的结束点。 
unity自带寻路Navmesh入门教程(二) - 阿赵 - 有爪的小羔羊阿赵

 

假如各位需要对越过OffMeshLink时候进行自己的控制,是需要另外写脚本的。我这里简单的介绍一下方法,有兴趣的朋友可以自己试试。

首先各位最好有用状态来控制角色的概念。比如人物可以分为站立、走路、跑步、上下楼梯、横向跳跃和往下掉落几种状态,针对NavMesh来说,人物简单的可以分为站立、正常的NavMesh寻路,和通过OffMeshLink移动几种状态。

先把 Auto Traverse Off Mesh Link选项取消。

然后,当人物在通过OffMeshLink移动的状态(可以用NavMeshAgent.isOnOffMeshLink来判断),获取到当前通过的OffMeshLink:

OffMeshLinkData  link = NavMeshAgent.currentOffMeshLinkData;

这样你就能获取到link的开始点和结束点的坐标(link.startPos和link.endPos),这时候你的人物就可以用最简单的Vector3.Lerp来进行移动,当人物的位移到达了结束点的坐标,人物的OffMeshLink移动状态就可以结束,又重新变回正常寻路或者站立的状态了。在这个Vector3.Lerp的过程中,你可以随意的控制人物的爬行或者跳跃的动作。

 

      到这里,第二节的内容结束了。到现在,各位应该已经可以基本掌握了NavMesh寻路的全部正常操作了。接下来,我会在第三节里面简单讲解一下NavMesh的稍微复杂的控制方法,希望大家继续支持阿赵。

      顺带一提,可能很多朋友希望我把工程文件提供下载。不过我觉得这样并不是一件好事,因为这几个例子都是很简单的操作,如果各位有耐心跟着阿赵一步步的做下来,应该可以得到你想要的结果。而如果没有耐心一步步的看下来,直接看工程文件,可能会忽略了很多重要的步骤的。



    继续介绍NavMesh寻路的功能,接下来阿赵打算讲一下以下两个例子,先看看完成的效果:

unity自带寻路Navmesh入门教程(三) - 阿赵 - 有爪的小羔羊阿赵 
unity自带寻路Navmesh入门教程(三) - 阿赵 - 有爪的小羔羊阿赵

 第一个例子对于喜欢DOTA的朋友应该很熟悉了,就是不同小队分不同路线进攻的寻路,红绿蓝三个队伍分别根据三条路线进攻。

第二个例子是动态的控制道路的开关。当吊桥打开时,道路不通,当吊桥放下时,道路可以通行。

先来说说第一个例子吧,第一个例子其实很简单,只需要在之前两节的基础上修改一下层的设置就可以了。

 

先来分析一下我们的地形,为了做这个例子,我准备了两个plane分别作为我方基地和地方基地,然后用plane简单的拼了三条线路。

在我方基地,准备了红绿蓝各三个的小兵(用胶囊代替)。当然小兵身上带着NavMesh Agent组件unity自带寻路Navmesh入门教程(三) - 阿赵 - 有爪的小羔羊阿赵

 如果把两个plane和三条线路都打上Navigation static的话,就和普通的寻路没有区别,三条路都能走。接下来我们进行层的设置。

 

还记得第一节里面讲过的怎么设置NavMeshLayer吧?

unity自带寻路Navmesh入门教程(三) - 阿赵 - 有爪的小羔羊阿赵

 现在我们需要设置Red、Blue和Green三个层,如上图所示。

 

unity自带寻路Navmesh入门教程(三) - 阿赵 - 有爪的小羔羊阿赵

 现在,我们可以选择路线一,然后在Navigation Layer里面选择Red层了。相应的,路线二选择Blue层,路线三选择Green层

unity自带寻路Navmesh入门教程(三) - 阿赵 - 有爪的小羔羊阿赵

 Bake出来后,会是上面的效果。

 

道路已经设置好了接下来我们对小兵身上的NavMesh Agent组件进行设置

unity自带寻路Navmesh入门教程(三) - 阿赵 - 有爪的小羔羊阿赵

选择蓝色的小兵,然后找到NavMesh Agent组件里面的NavMesh Walkable选项,这里就是人物能通过的层的选择了。按照刚才层的设计,蓝色的小兵需要勾选Blue层 ,把Red层和Green层取消选择。

 

同理,把红色小兵和绿色小兵的NavMesh Walkable层处理一下。

unity自带寻路Navmesh入门教程(三) - 阿赵 - 有爪的小羔羊阿赵

 现在,我们可以运行了,移动目标点到敌方基地,三种不同颜色的小兵就会根据不同的路线寻路进攻了。

unity自带寻路Navmesh入门教程(三) - 阿赵 - 有爪的小羔羊阿赵
我们第一个目标也就完成了。
 
 
接下来说一下第二个例子
unity自带寻路Navmesh入门教程(三) - 阿赵 - 有爪的小羔羊阿赵
这个例子我准备了两个平台,中间是一个活动的吊桥,一个带NavMesh Agent组件的角色模型,一个目标点
如果按照之前的操作,我们可以轻易的让角色在任意位置寻路,但为了让吊桥升起的时候角色不能通过吊桥,我们需要对吊桥的NavMesh层进行一些设置。
 
unity自带寻路Navmesh入门教程(三) - 阿赵 - 有爪的小羔羊阿赵
和刚才一样,我们要预先设置了一个叫做bridge的层(在第一节的时候做过)。
 
 
unity自带寻路Navmesh入门教程(三) - 阿赵 - 有爪的小羔羊阿赵
同样的,吊桥选择bridge层
 
这里的操作和上面的例子没什么区别,但这次角色身上的NavMesh Walkable不需要设置,直接Everything就行了。
 
      到了这里,我们需要通过脚本来控制人物是否能通过吊桥。这里需要用NavMeshAgent.walkableMask来动态修改NavMesh Walkable的值。
      关于吊桥怎样升降,这不是本次讨论的内容,你可以选择直接用位移来控制,或者吊桥直接做好开关的动画也行。
      之前说过,各位最好要有习惯用状态来控制物体。这里的吊桥会有2种状态,一种是开状态,一种是关状态。当开状态时,吊桥断开,人物不能通行,关状态时,吊桥闭合,人能通行。给予这两种状态,我们给人物身上的NavMeshAgent.walkableMask赋值。
写一段很简单的代码吧:
    private bool open = false;
    private NavMeshAgent agent;
void Start () {
  agent = gameObject.GetComponent<NavMeshAgent>();
 
 }
void Update(){
if(open) agent.walkableMask = 1;
else agent.walkableMask = -1;
}
 
可以了,就是这么简单。
这里为了简便,把赋值写在了UpDate里面,其实这样做是不正确的,没必要每帧都检测赋值,只需要把这个赋值写在吊桥开关的控制里面就行了。
我来解释一下其中的意思:
定义了一个状态的开关open,当吊桥打开时open= true;当吊桥闭合时,open = false;至于这个状态时怎样赋值的,各位可以自己试试想办法。
然后假设这个脚本是放置角色身上的,那么在start的时候就获取角色身上的NavMesh Agent组件。当然了,你也可以把脚本放在其他的地方,然后通过赋值来指定agent。
当open为true的时候,人物的walkableMask = 1,意思是只有第一层(就是默认的Default)可以让玩家通行。
当open为false的时候,人物的walkableMask = -1,意思是所有层(Everything)都可以让玩家通过。
unity自带寻路Navmesh入门教程(三) - 阿赵 - 有爪的小羔羊阿赵
 
从自定义层的界面我们可以总结一下,每一个层的可通过值,其实就是全面所以层的值相加的总和再加1。或者说是2的(n-1)次方。
除了指定本身的层意外,还可以指定多个层,比如这里假如你想mix一个Default和bridge层都能通过,你可以设定walkableMask = 9,也就是1+8。
 
 
      到此为止,阿赵我对于Unity自带的NavMesh寻路的介绍就结束了。至于NavMesh或者NavMesh Agent组件的各个属性和方法,API文档里面有具体的说明,有兴趣可以具体去看看,我就不一一解释。有很多变化的用法,各位可以自己尝试一下。谢谢大家的支持!
unity自带寻路Navmesh入门教程
0 0
原创粉丝点击