Unity3D—–寻路系统

寻路系统

  • 一、寻路方式
  • 二、实现寻路方法
    • 1、实现寻路步骤
    • 2、代码测试
  • 三、关于Navigation中属性的介绍
  • 四、组件Nav Mesh Obstacle的使用
  • 五、组件Off Mesh Link的使用
  • 六、用代码实现勾选不同的寻路区域
  • 七、注意问题

一、寻路方式

  • 路点寻路
  • 单元格寻路
  • 网格寻路

二、实现寻路方法

  1. 确定寻路者
  2. 烘培寻路路面
  3. 程序实现寻路算法

1、实现寻路步骤

  1. 将场景中不动的物体勾选static
  2. 烘培寻路网格
    Unity2019:打开window->AI->Navigation面板;如下图
    在这里插入图片描述
    点击Bake完成网格路面的烘培。
  3. 给需寻路的物体添加NavMeshAgent组件(Unity主要通过NavMeshAgent组件实现自动寻路的功能,角色添加NavMeshAgent组件后,就可以在NavMesh寻路网格上寻找最优路径找到目标)
    选中物体,然后在属性面板中点击Add Component,搜索Nav Mesh Algent,添加此组件。
  4. 给需要寻路的物体添加脚本
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寻路系统的动态碰撞有局限性