Navigation
基本概念
Navigation是Unity自带的导航,具备了基本的Bake(烘焙)NavMesh(导航网格)和NavMashAgent(导航代理)等基本导航功能;
NavMeshComponents则是unity官方GitHub上的一套功能更强大的扩展了Navigation的工具。能做到更多例如动态烘焙,预设体和设置跳跃路径等。
使用流程
- 打开Navigation面板
Unity菜单栏Window→AI→Navigation,然后会出现在Inspector面板右边 - 设置烘培参数
Bake Agent Size
Agent Radius -- 智能体大小
Agent Height -- 智能体高度
Max Slope -- 智能体能走的路的最大的斜率,超过这个值,智能体就不能走在那条路线上
Step Height -- 智能体可以爬上去的最大的高度,上台阶,如果台阶高过这个值,智能体无法爬上去这个值必须小于智能体高度
Generated Off Mesh Links
Advanced
Manul Voxel Size -- 网格分割,这个值越小,分割出的网格越细密,性能消耗越大
Min Region Area -- 寻路能识别的最小的区域,小于这个值的区域不会被当做可寻路的区域,就不会被烘焙
Height Mesh -- 是否开启高度网格,开启后,路线就不是平的了,会像上楼梯突然网上,或者往下,不开启路线就是平的,楼梯相当于斜着放的平板,不会有突然的上下,这个可以让寻路更精确,楼梯就是楼梯,斜面就是斜面,可以被区分 - 设置行走区域
选择场景中可作为角色移动的collider,设定Static为Navigation Static ,用于标记该物体可行走
OfferMeshLink:连接2块NavMesh,设置Star起始点和End结束点,则视为可以在这2点间移动,多用于攀爬和跳跃。 - 烘培 – 在Navigation窗口里面Bake点击按钮进行烘培(大概几秒钟),然后生成的蓝色区域表示可行走
- 角色添加寻路控制器:给角色或AI添加NavMeshAgent组件用于角色控制,可以设定类型/移动速度/宽高等属性
- 使用API进行寻路
常用变量和API
官方API地址 obstacleAvoidanceType = NoObstacleAvoidance : 设置不碰撞推挤
NavMeshAgent.destination = V3 :设置寻路目的地,并马上移动;
NavMeshAgent.isStopped :启动/停止寻路;
NavMeshAgent.pathPending :是否正在寻路;
NavMeshAgent.corners:路径点
NavMeshAgent.remainingDistance :与目的地距离
ResetPath :清空当前路径。
Resume() :停止游戏角色进行移动,并重新开始移动(原路径)
Wrap(V3) :将物体瞬移到目标点
NavMeshComponents
如何启动
- 官方GitHub地址
- 版本要求:Unity 5.6 or newer
- 把Assets/NavMeshComponents复制到自己的项目内。
Demo示例
- 1_multiple_agent_sizes:演示门的设定,让不同大小的Agent只能通过适合自己大小的门。可以创建不同NavMeshSurface来制定不同的宽高等属性的Agent,即可bake出不同的NavMesh
- 2_drop_plank:动态烘焙运行时产生的木板,产生一个rigidbody木板isSleep后烘焙 .
- 3_free_orientation:自由设定重力方向
- 4_sliding_window_infinite:只动态烘焙角色一定距离内的区域,并且不断刷新沙盒地图
- 5_sliding_window_terrain:如上,但不刷新地图
- 6_modify_mesh:动态改变mesh高度并烘焙 .
- 7_dungeon:地牢,引入了新的过度mesh方式-NavMeshLink可是设定一定长宽的导航路径,比起MeshOfferLink更方便和更有效率,并可以通过角色上的AgentLinkMover来设定行动方式Teleport,NormalSpeed,Parabola,甚至Curve自定义曲线。
- 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)让导航更偏向走什么路
一些问题和实验
- AngularSpeed属性无效, 解决方法一般是自己用代码来控制旋转。
[1]要设置Agent中的AngularSpeed为0,或者代码设置navmeshAgent的属性updateRotation为false
[2]要禁用Animator的ApplyRootMotion - 调用NavMeshagent.destination设置目标点,如果目标点是不可达的点,那么结果是destination存放了离目标点最近的点。并且也会让寻路者移动到最近点。移动到最近的点后,remainingDistance为0。
- 调用NavMeshagent.destination设置目标点时,目标点的Y值将会被设置为离agent最近的NavMesh的Y值。
- 设置NavMeshAgent的enable刷新位置,Unity内部会寻找NavMeshagent最近的NavMesh。最把它放在NavMesh上。
- 调用NavMeshagent.CalculatePath计算路径是否可达,如果传入了无效点path.status会显示PathInvalid。如果点之间不可以到达显示PathPartial,如果可达显示PathComplete
- avoidancePriority越小,优先级越高,它会很不友好地把其它优先级低的物体给挤开
- NavMeshObstacle不能和NavMeshagent同时使用。否则物体将会试图自己躲开自己。表现就是乱跳
- 总的来说,Unity寻路对动态物体躲避做得不好。如果avoidancePriority无法满足需求的话,请选用astar pathing这种第三方插件。
- NavMeshAgent启用的时候,CharacterController就不起作用。CharacterController在遇到有碰撞的障碍物时,会尝试微调绕过物体。
- 导航在服务器中使用:有工具把unity的mesh导出成recast格式的mesh文件,然后自带的demo生成寻路文件。研究下吧,会c++就不难,一个星期可以搞定