Unity之网格导航

前言:在游戏中经常出现怪物自己会走路,人物跟随鼠标点击位置进行移动,那么这些功能是怎么实现的呢?通过本节内容的学习,你会对自动寻路的原理有一个初步的认识。当然了如果想像英雄联盟里面的人物那样带点击的特效的话,还需要用到粒子系统方面的知识,好了,废话不多说了,咱们开始吧


1. 认识网格导航组件

Nav Mesh Agent(网格导航代理)

Unity之网格导航_第1张图片
  • Radius:agent的半径,用于计算该agent和其他agent、obstacle的碰撞。
  • Height:agent的高度,agent可以通过的头顶障碍最小高度。
  • Base offset:agent圆柱碰撞体中心点的偏移值。当Agent创建后,圆柱碰撞体显示过高或过低,用于将其调整到地面。
  • Speed:agent移动的最大速度(世界空间中以秒单位计算)
  • Angular Speed:agent最大的旋转速度(角度每秒)
  • Acceleration:agent最大的加速度(世界空间单位每秒的平方)
  • Stopping distance:agent靠近目标时停下的距离
  • Auto Braking:自动刹车,当启用的时候agent会在到达终点时慢慢停下,你应该在角色需要平滑地巡逻几个固定点时,禁用它。
  • Quality:障碍回避的质量值,如果你有大量的agent就可以降低该值节约CPU的资源,将它设置为0,则只会处理碰撞,不会尝试规避其他agent和obstacle。
  • Priority:agent会重视该值比自己小的,而忽略该值比自己大的。该值范围为0到99,数字越低意味着高权限,权限越高(越小的值)会被其他agent重视而回避。
  • Auto Traverse OffMesh Link:需要agent自动通过off-mesh link的时候设置为true,当想要使用动画或其他特殊的方法通过off-mesh link时设为false。
  • Auto Repath:启用时,agent会在到达局部路径的终点时,尝试再次寻找路径。当没有通向目标的路径时,它会生成一个离目标最近的点作为当前的一个目标。(我尝试下来发现,当目标点不可达,勾选该选项的agent尝试寻找临近目标点的欲望比不勾选的要大)
  • Area Mask:AreaMask描述了agent会在哪些烘培的区域中寻找路径。当你准备烘培NavMesh时,你可以指定区域的类型,比如你想让阶梯作为一个特殊的区域,并且禁止某些角色使用阶梯。
在使用Agent的时候,大家可能发现了Agent有Radius属性,在我们烘培NavMesh的时候设置的圆柱体也有Radius属性,两者有什么区别呢?
在寻路的时候有两个阶段,第一阶段只考虑烘培NavMesh并寻找一条可行的路径,而第二阶段Agent就已经在前往目的地的路上了,它会考虑其他agent和obstacle,并尽量避开他们。
烘培时候的Radius就对应第一阶段的生成NavMesh,而Agent上的Radius只在第二阶段使用。就比如说,有一条小径,你有一只大怪是通过不了该路径的,但烘培时候的Radius设置的比较小,虽然Agent的Radius可能设置的很大,但这只大怪还是会使用该小径通过。
所以要理解寻路的两个阶段,再强调一遍,第一阶段没有开始真正的寻路不考虑其他的agent和obstacle,只看NavMesh,而第二阶段Agent已经在行走,而会尽量避开其他agent和obstacle。

Off Mesh Link(分离网格连线)

OffMeshLink组件允许你在区域中给Agent提供一些小近路,使Agent能快速通过,比如跳过栅栏、通过一扇门。


Unity之网格导航_第2张图片
  • Start:物体描述的开始点。
  • End:物体描述的结束点。
  • Cost Override:如果该值是正的,使用它在处理需求路径时计算路径的代价值,否则会使用默认的代价值(游戏物体所属区域的代价值)。如果代价值设置超过3.0,经过该off-mesh link会比经过三倍的默认NavMesh区域还多。当你想用Agent初始化偏爱的路径时,该代价值非常有用。当然最好是在移动中清晰比较长的距离中使用。
  • Bi Directional:如果启用,则该link是双向的,否则只能从Start到End。
  • Activated:指定该link会不会在寻路的时候使用(在设置为false的时候被忽略)
  • Auto Update Position:启用的时候,Off-Mesh Link会自动重新连接start和end的坐标,如果禁用,则只使用启用时候的坐标,即使后来坐标移动了也不会改变。
  • Navigation Area:描述link所属的NavMesh区域类型,该区域类型会允许你在相似类型区域中应用该区域的通路代价值,并且防止一些特定的Agent使用该通路,使用Agent的AreaMask属性来控制。

Nav Mesh Obstacle(网格导航障碍)

Unity之网格导航_第3张图片
  • Shape:obstacle的几何形状,选择物体最合适的形状,有两种Box方块和Capsule胶囊体。
  • Box/Center:方块形状的中心点,与Transform的Position有关。
  • Box/Size:方块的大小尺寸。
  • Capsule/Center:胶囊体形状的中心点,与Transform的Position有关。
  • Capsule/Radius:胶囊体的半径。
  • Capsule/Height:胶囊体的高度。
  • Carve:当Carve该选项被勾选,Obsacle该物体会在NavMesh上制造一个空洞。
  • Move Threshold:Unity会在Obstacle移动该距离下,将其处理为移动状态,使用该属性设置移动更新Carve空洞的频率。
  • Time To Stationary:Obstacle停止运动后,经过多少时间(秒)会被处理为静止状态。
  • Carve Only Stationary:启用时,Obstacle仅会在静止时被处理成空洞,详见官方文档(废话)。这里有几个小细节需要注意,禁用该选项时,空洞的重新计算是隔一帧计算一次,就是两帧计算一次。然后最好启用该选项,因为每次空洞的重新计算比较费时。官方文档中举了两个适用的场景:木桶、箱子之类会受力停止的启用选项,而像坦克缓慢移动的,则可以禁用该项。

Navigation面板(导航面板)

Agents(网格导航代理)

Unity之网格导航_第4张图片
  • Agent Types:导航代理类型
  • Name:导航代理名字
  • Radius:导航代理半径
  • Height:导航代理高度
  • Step Height:能上去的台阶高度
  • Max Slope:最大的坡度

Areas(导航区域)

Unity之网格导航_第5张图片
  • 前三个是Unity内置的Walkable(能走的),Not Walkable(不能走的),Jump(跳)
  • 其他的用户用来自定义

Bake(烘焙参数面板)

Unity之网格导航_第6张图片
  • Radius:具有代表性的物体半径,半径越小生成的网格面积越大。
  • Height:具有代表性的物体的高度。
  • Max Slope:斜坡的坡度。
  • Ste Height:台阶高度。
  • Drop Height:允许最大的下落距离。
  • Jump Distance:允许最大的跳跃距离。
  • Min Region Area:网格面积小于该值则不生成导航网格。
  • Width Inaccuracy:允许最大宽度的误差。
  • Height Inaccuracy:允许最大高度的误差。
  • Height Mesh:勾选后会保存高度信息,同时会消耗一些性能和存储空间。

Object(物体参数面板)

Unity之网格导航_第7张图片
  • Navigation Static:勾选后表示该对象参与导航网格的烘培。
  • OffMeshLink Generation:勾选后可跳跃(Jump)导航网格和下落(Drop)。
  • Navigation Area:可以导航的区域

2. 使用网格导航组件实现跟随物体位置移动

搭建环境

Unity之网格导航_第8张图片
  • 平面障碍物
  • 使用Off Mesh Link制作的路径
  • 楼梯
  • 斜坡
  • 断层
  • 洞口

3. 烘焙导航网格

  • 打开导航面板


    Unity之网格导航_第9张图片
  • 选中要烘焙的地形对象


    Unity之网格导航_第10张图片
    • Navigation>>Object>>All,Navigation Static勾选


      Unity之网格导航_第11张图片
    • Navigation>>Bake
      • 调整半径让其尽可能多的包含地形对象
      • 调整高度(可以进入洞口)
      • 调整最大坡度(可以上的坡度)
      • 调整台阶高度(可以走上楼梯)
      • 调整下落高度(可以从高出落下)
      • 调整跳的距离(可以跳过断层)
      • 点击Bake
  • 烘焙之后Scene视图中的效果,所有显示蓝色的网格是可以导航到的位置


    Unity之网格导航_第12张图片
  • 设置能够跳跃断层


    Unity之网格导航_第13张图片
    • 选中能够跳跃的对象,Navigation>>Object>>All>>Generate OffMeshLinks勾选,然后进入Bake面点击Bake
  • 烘焙之后Scene视图中的效果,Plane出现了箭头指向了另一头的Plane


    Unity之网格导航_第14张图片
  • 使用Off Mesh Link制作的路径
    • 创建一个Cube放在第一个Plane的边缘,克隆一个放在第二个Plane的边缘
    • 在第一个Cube身上添加Off Mesh Link组件,把第一个Cube拖到组件的Start中,把第二个Cube拖到组件的End中,这样就可以从第一个Plane的第一个Cube的位置到第二个Plane的第二个Cube的位置;中间的黑线就是Off Mesh Link制作的路径
Unity之网格导航_第15张图片

4. 创建角色和跟随物体

  • 创建一个胶囊体当作小人


    Unity之网格导航_第16张图片
  • 创建一个Cube当作跟随物体


    Unity之网格导航_第17张图片

5. 在角色身上添加Navigation Mesh Agent组件

Unity之网格导航_第18张图片

6. 脚本

  • 功能:让角色导航到跟随物体的位置
  • 把脚本挂载到角色身上
  • 把跟随物体拖到脚本的实例对象上
Unity之网格导航_第19张图片
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;//人工智能的命名空间

//按下鼠标左键玩家跟随移动
//挂载对象:Player游戏对象
public class Test01 : MonoBehaviour
{
    //玩家要到达的位置
    public Transform TrCube;
    //网格导航代理
    private NavMeshAgent mNMA;
    void Start()
    {
        //得到NavMeshAgent组件
        mNMA = GetComponent();
    }


    void Update()
    {
        //到指定的位置(终点的位置)
        //方法一:通过属性
        mNMA.destination = TrCube.position; 
        //方法二:通过方法
        //mNMA.SetDestination(TrCube.position);
    }
}

参考文章:Unity3D 官方文档 NavMesh三个组件的翻译与解释 自动寻路需要知道的细节


最后:网格导航的所有内容就到这里了,通过这篇文章咱们认识了网格导航的三个基本组件以及导航面板,通过做一些小demo去加深理解,好了,这期内容就到这里了,大家再见

你可能感兴趣的:(Unity之网格导航)