寻路系统
- 一、寻路方式
- 二、实现寻路方法
- 1、实现寻路步骤
- 2、代码测试
- 三、关于Navigation中属性的介绍
- 四、组件Nav Mesh Obstacle的使用
- 五、组件Off Mesh Link的使用
- 六、用代码实现勾选不同的寻路区域
- 七、注意问题
一、寻路方式
- 路点寻路
- 单元格寻路
- 网格寻路
二、实现寻路方法
- 确定寻路者
- 烘培寻路路面
- 程序实现寻路算法
1、实现寻路步骤
- 将场景中不动的物体勾选static
- 烘培寻路网格
Unity2019:打开window->AI->Navigation面板;如下图
点击Bake完成网格路面的烘培。 - 给需寻路的物体添加NavMeshAgent组件(Unity主要通过NavMeshAgent组件实现自动寻路的功能,角色添加NavMeshAgent组件后,就可以在NavMesh寻路网格上寻找最优路径找到目标)
选中物体,然后在属性面板中点击Add Component,搜索Nav Mesh Algent,添加此组件。 - 给需要寻路的物体添加脚本
1 2 3 4 5 6 7 8 9 10 11 | public class FindWayByNav : MonoBehaviour { public Transform target; private NavMeshAgent nav; private void Start() { nav = this.GetComponent<NavMeshAgent>(); //SetDestination方法即为寻路方法,参数为目标物体的三维向量 nav.SetDestination(target.position); } } |
2、代码测试
用以上代码进行测试结果如下:
因无法发布视频,所以实际效果可按一下例子自行测试
红色Cube为目标物体,黄色Sphere为寻路物体,图中浅蓝色路线为烘培的网格路线。
三、关于Navigation中属性的介绍
- Cost:寻路区域消耗度,数值越大,从此寻路区域消耗越大。寻路物体在区域消耗数值一样的情况下,会选择最优(最近)路面寻路,但如果寻路区域的消耗数值不同,会根据消耗的数值,越小越最优进行寻路。
- 有关Nav Mesh Agent的属性等介绍,详情请参见官方说明
https://docs.unity3d.com/Manual/class-NavMeshAgent.html
四、组件Nav Mesh Obstacle的使用
- 在物体(命名为寻路物体)的寻路过程当中,若是直接添加一个物体(命名为障碍物体)作为路线上的障碍,但是寻路物体在按照路线进行前进时,并不会受到障碍物体的阻挡,而是直接穿透过物体继续前行。
为解决此问题,我们就需要给障碍物体添加Nav Mesh Obstacle组件
添加此组件之后,可看到障碍物体有一个绿色边框的长方体框住了障碍物体,此时寻路物体再次前行就会受到障碍物体的阻挡,有关此组件中属性说明,请参见官方说明文档
http://docs.unity3d.com/Manual/class-NavMeshObstacle.html
五、组件Off Mesh Link的使用
当寻路物体需要到另一个地面时,而两个地面之间没有连接,那么在进行烘培网格路面时,并不会将两个路面上的网格路面连接起来,那么如图(忽略障碍物体)所示,
寻路物体就不能够到达另一块地面到达目标物体身边。
为解决此问题,有两种解决方案:
(1)、在两块路面之间再加一个面板,进行网格路面的烘培即可。
(2)、使用Off Mesh Link组件进行实现。
Off Mesh Link的使用方法:在两块路面上,分别添加两个空的物体,并为其中一个物体添加此组件,再设置此组件的属性,起始点和目标点,再进行网格路面的烘培即可,实际效果如下:
注意:两边地面上进行连接的点不能在烘培的蓝色网格之外,否则无效,且两点间的弧线为不加粗的!
温馨提示:使用此组件无法调节物体在两点间移动的速度,如需调节速度,建议使用第一种方法。
六、用代码实现勾选不同的寻路区域
GetComponent ().areaMask=8;
寻路区域每一个区域都是2的幂,如下图所示,通过幂的数值进行设置
- 若是想要选择多条路径,则将幂的数值进行相加再赋予areaMask即可。
- Everything->-1,Nothing->0
七、注意问题
- 避免重复计算(位置不变的话就不要重新计算)
即,如果需要寻找的静态物体位置是保持不变得话,那就不需要将组件NavMeshAgent的SetDestination(Vector3 target)方法放在Update/(循环)中调用进行重复计算运行; - Unity寻路系统的动态碰撞有局限性