Navigation

基本概念

Navigation是Unity自带的导航,具备了基本的Bake(烘焙)NavMesh(导航网格)和NavMashAgent(导航代理)等基本导航功能;

NavMeshComponents则是unity官方GitHub上的一套功能更强大的扩展了Navigation的工具。能做到更多例如动态烘焙,预设体和设置跳跃路径等。

使用流程

  1. 打开Navigation面板
    Unity菜单栏Window→AI→Navigation,然后会出现在Inspector面板右边
  2. 设置烘培参数
    Bake Agent Size
    Agent Radius -- 智能体大小
    Agent Height -- 智能体高度
    Max Slope -- 智能体能走的路的最大的斜率,超过这个值,智能体就不能走在那条路线上
    Step Height -- 智能体可以爬上去的最大的高度,上台阶,如果台阶高过这个值,智能体无法爬上去这个值必须小于智能体高度
    Generated Off Mesh Links
    Advanced
    Manul Voxel Size -- 网格分割,这个值越小,分割出的网格越细密,性能消耗越大
    Min Region Area -- 寻路能识别的最小的区域,小于这个值的区域不会被当做可寻路的区域,就不会被烘焙
    Height Mesh -- 是否开启高度网格,开启后,路线就不是平的了,会像上楼梯突然网上,或者往下,不开启路线就是平的,楼梯相当于斜着放的平板,不会有突然的上下,这个可以让寻路更精确,楼梯就是楼梯,斜面就是斜面,可以被区分
  3. 设置行走区域
    选择场景中可作为角色移动的collider,设定Static为Navigation Static ,用于标记该物体可行走
    OfferMeshLink:连接2块NavMesh,设置Star起始点和End结束点,则视为可以在这2点间移动,多用于攀爬和跳跃。
  4. 烘培 – 在Navigation窗口里面Bake点击按钮进行烘培(大概几秒钟),然后生成的蓝色区域表示可行走   
  5. 角色添加寻路控制器:给角色或AI添加NavMeshAgent组件用于角色控制,可以设定类型/移动速度/宽高等属性 
  6. 使用API进行寻路

     

常用变量和API

官方API地址 obstacleAvoidanceType = NoObstacleAvoidance : 设置不碰撞推挤
NavMeshAgent.destination = V3 :设置寻路目的地,并马上移动;
NavMeshAgent.isStopped :启动/停止寻路;
NavMeshAgent.pathPending :是否正在寻路;
NavMeshAgent.corners:路径点
NavMeshAgent.remainingDistance :与目的地距离
ResetPath :清空当前路径。
Resume() :停止游戏角色进行移动,并重新开始移动(原路径)
Wrap(V3) :将物体瞬移到目标点
 

NavMeshComponents

如何启动

  1. 官方GitHub地址
  2. 版本要求:Unity 5.6 or newer
  3. 把Assets/NavMeshComponents复制到自己的项目内。

Demo示例

  1. 1_multiple_agent_sizes:演示门的设定,让不同大小的Agent只能通过适合自己大小的门。可以创建不同NavMeshSurface来制定不同的宽高等属性的Agent,即可bake出不同的NavMesh 
  2. 2_drop_plank:动态烘焙运行时产生的木板,产生一个rigidbody木板isSleep后烘焙                                                     .
  3. 3_free_orientation:自由设定重力方向
  4. 4_sliding_window_infinite:只动态烘焙角色一定距离内的区域,并且不断刷新沙盒地图
  5. 5_sliding_window_terrain:如上,但不刷新地图
  6. 6_modify_mesh:动态改变mesh高度并烘焙                                                                                                   .                        
  7. 7_dungeon:地牢,引入了新的过度mesh方式-NavMeshLink可是设定一定长宽的导航路径,比起MeshOfferLink更方便和更有效率,并可以通过角色上的AgentLinkMover来设定行动方式Teleport,NormalSpeed,Parabola,甚至Curve自定义曲线。 
  8. 7b_dungeon_tile_prefabs:使用导航预制体
    太垃圾了 居然新版不能用了 不过核心代码在Editor自己写调用就好了
    发现有个哥们修好了

预制烘培流程

  • 打开Navigation - Unity菜单栏Window→AI→Navigation
  • 设置烘培条件 – 因为我们游戏不存在碰撞和肥瘦设定,设置Agent Radius为0.1
  • 选择需要烘培的Prefab拖拽到场景中
  • 给预设最外层添加脚本NavMeshPrefabInstance
  • 编辑预设的可行区域
  • 在面板勾选可行走物体Navigation Static属性,用于标记该物体可行走
  • 添加连接出口,在出口添加GameObject然后添加脚本NavMeshLink,一般只需要设置X偏移和Width即可
  • 应用预设,点击Apply,然后点击Select自动选回Asset里的预设
  • 点击脚本上的Bake烘培按钮,查看效果
    预制体烘培流程(图崩了 如果有人看不懂就补)

一些技巧

1.在Navigation的Object里设置Area来增加花费(cost)让导航更偏向走什么路

unity navigation Areas 设置提交 unity navigation面板在哪_API


一些问题和实验

  1. AngularSpeed属性无效, 解决方法一般是自己用代码来控制旋转。
    [1]要设置Agent中的AngularSpeed为0,或者代码设置navmeshAgent的属性updateRotation为false
    [2]要禁用Animator的ApplyRootMotion
  2. 调用NavMeshagent.destination设置目标点,如果目标点是不可达的点,那么结果是destination存放了离目标点最近的点。并且也会让寻路者移动到最近点。移动到最近的点后,remainingDistance为0。
  3. 调用NavMeshagent.destination设置目标点时,目标点的Y值将会被设置为离agent最近的NavMesh的Y值。
  4. 设置NavMeshAgent的enable刷新位置,Unity内部会寻找NavMeshagent最近的NavMesh。最把它放在NavMesh上。
  5. 调用NavMeshagent.CalculatePath计算路径是否可达,如果传入了无效点path.status会显示PathInvalid。如果点之间不可以到达显示PathPartial,如果可达显示PathComplete
  6. avoidancePriority越小,优先级越高,它会很不友好地把其它优先级低的物体给挤开
  7. NavMeshObstacle不能和NavMeshagent同时使用。否则物体将会试图自己躲开自己。表现就是乱跳
  8. 总的来说,Unity寻路对动态物体躲避做得不好。如果avoidancePriority无法满足需求的话,请选用astar pathing这种第三方插件。
  9. NavMeshAgent启用的时候,CharacterController就不起作用。CharacterController在遇到有碰撞的障碍物时,会尝试微调绕过物体。
  10. 导航在服务器中使用:有工具把unity的mesh导出成recast格式的mesh文件,然后自带的demo生成寻路文件。研究下吧,会c++就不难,一个星期可以搞定