找回密码
 立即注册
查看: 683|回复: 0

[简易教程] Unity寻路插件(A* Pathfinding)入门教程三:使用导航网格(navmeshes)

[复制链接]
发表于 2020-12-23 13:17 | 显示全部楼层 |阅读模式
本系列的教程文章基于 A*Pathfinding Project 4.2.8的官网教程翻译,每一章节的原文地址都会在教程最下方给出。
这篇开始就是入门教程的第二部分啦。
教程会涵盖两种普通的导航网格图,即手动生成的(modelled by hand)和由重构图(recast graph)自动生成的导航网格。无论你在游戏中使用哪种方式的导航图,这两种模式都非常有用,所以希望大家能够两者都学。
(译注:Unity的导航网格虽然好用,但是都是静态生成的,无法更改,A*提供了动态生成navMesh的方式)。
什么是导航网格

在第一部分我们使用的都是栅格类型(grid graph)的网格。但是A*插件功能非常强大,当然不会只支持一种网格类型!它理所当然的也支持导航网格类型。
GridGraph是由一些节点按照栅格的方式排列组成的,所以他能够匹配绝大多数的使用场景。但是想象一下,如果你的游戏里有一个巨大的草原,你需要给每一个单位的草地都生成一个格子来标识一个蒙古包不能行走是不是巨大的浪费?有没有更好的方法只用少量的节点标识一大片的可行走区域,然后多一些的节点去标识这些小的障碍物呢?那么我们的主角就登场了:导航网格(navmeshes)。导航网格用很多的多边形(本示例 使用的是三角形)来呈现世界,标识出角色可行走的地表。
如你所见,这些导航网格并不是相同大小的节点,但它其实可以动态调节每个节点的大小。所以最终的结果就是在大量“无人区”(empty areas)使用较大、较少的节点来避免浪费,障碍物多的地方使用较小、较多的节点来精确标识障碍物。当节点变少的时候,寻路的速度就会变快了。同时,它们还能标识分层环境下的网格状态。(这个特性只在pro版本里使用 LayeredGridGraph)
好处讲完了,那坏处呢?最大的问题可能就是导航网格图的生成需要花费大量的时间。(如果是手动生成,则需要大量的模型)。例如GridGraph example scene场景里 如果要扫描整个GridGraph 可能要花费100-200ms(取决于计算机性能)才能生成一个重构图(recast graph),有时候甚至要花费数秒。并且他们相对来说还是静态的,当你生成完了之后,你很难再去更新它,哪怕只是很小的一块数据。最快最有效的方法可能就是使用导航网格裁切(navmesh cutting),但对于重构图来说,也可以通过异步的方式去重计算和更新个别的Tiles。(tiles 会在后面的recast graph章节详细讲解)但相对来说仍然很慢。
创建一个导航网格

导航网格的创建分为两种方式,手动和自动。自动创建只能在Pro版本里才能使用。
可以从以下两个地方查看创建方式:
    手动:
自动:
在导航网格上移动

上一篇教程,我们已经写了一个单的移动脚本。我们其实可以仍然沿用这个脚本,但是做些更完善的工作。那么接下来就介绍一下RichAI脚本,非常适用于导航网格类型的移动。
创建一个物体,绑定richAI组件,然后它会自动帮你把Seeker组件也绑上。为了能在Unity里看到它,我们给他添加一个胶囊他的子节点。把胶囊往上移动一个单位来对齐锚点。因为RichAI是假定锚点在脚上的。
你需要从刚才的胶囊体上移除碰撞,不然你就要在RichAI的MASK参数里配置属性来排除这些碰撞体。但是,为什么要移除呢?这是因为RichAI组件会用射线去检测地面在哪,如果射线击中了自己身上的碰撞,就会发生神奇的事情。当然你也可以使用CharacterController组件啦,但是如果你游戏里有很多的角色要控制,就不推荐使用这个组件,它的性能损耗太大了。
我们需要另外一个脚本来告诉AI,应该移动到什么地方。把AIDestinationSetter 组件绑定到RichAI组件相同的物体上。这个组件上有一个Transform的参数Target,这个脚本所做的事情就是保持AI朝着目标点前进。再new一个物体叫Target,把Target拖拽给AIDestinationSetter 的Target参数,就大功告成了。
下面的截图是一个老版本的示例,所以Target的参数是直接存在RichAI上而不是AIDestinationSetter 上的。
现在点击Play按钮,你会看到将囊体开始朝着目标移动了。
RichAI是为导航网格的类型特意去写的,它会强制让代理在任何时候都呆在导航网格上。与其他演示的示例不同的是,它并不支持修饰符。这是因为他并没有一个路点(waypoint)的list,而是一个节点(nodes)的list,它的优势是即使在行进的过程中被外力推离了原路径,也能自动修正而不需要重新计算。
RichAI的参数太多了,本章教程也不去详细解释,可以参考这里来获取详细参数信息:
备注

如果你不在寻路里使用RichAI组件,那么我推荐你绑定funnel modifier组件到Seeker上,他会帮助你简化以及美化路径。
导航网格图有时候会给你提供次优路径。这是因为寻路是通过多边形(三角形)的中心点进行的,如果一个过大的多边形(三角形)和一个过小的相邻的时候,寻路总是会选择小的多边形行走。
上面展示的就是这种情况,绿色的是实际路径,它绕了三面。橘色的才是最优路径。
这个方式没有什么太好的解决方案,所以只能避免把过大和过小的多边形放在一起。但是对于后面要将的重构图(recast graph)你就可以指定一个tile size 来分离过大和过小的三角形,最大的边长也同样可以设定。
文章原地址:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-23 11:37 , Processed in 0.064731 second(s), 23 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表