开发者博客:如何用Unity做游戏中寻路导航
如今,大多数MMO游戏都具备自动寻路功能。玩家点击场景中的某个位置,角色就能自动寻路前往该地点。即便途中存在诸多障碍物,角色也会自动绕过,最终抵达终点。在使用Unity开发手游时,实现自动寻路有多种方式。
近期,一位海外开发者在博客中分享了他使用Unity引擎重新制作此前研发的Flash游戏寻路导航的经验,希望能对大家有所帮助。
大家好,我最近一直在忙于用Unity引擎重新制作一款2006年的Flash游戏。尽管我们在《Arrival in Hell》项目上已经投入了一年多的时间,但我打算从头开始撰写这篇开发者博客,以便让读者有更完整的了解。
如果你对这款游戏不太熟悉,我简单介绍一下。这是一款2006年由我和朋友Eduardo Mojica、Richard Rout三人共同研发的点击式冒险游戏,如今我们将使用Unity引擎对其进行重制。我从事游戏编程和开发已有约十年经验,但这是我首次使用Unity引擎开发游戏。
在着手其他工作之前,我想先谈谈玩家角色的移动问题。由于这款游戏是真正的3D游戏,玩家角色需要在3D空间中进行寻路。幸运的是,Unity引擎具备一些出色的内置寻路功能。你只需打开“窗口 - 导航(Navigation)”,选择想要使用的物体并将其放入路径中,然后将它们标记为“导航静态(Navigation static)”,这样就能告知Unity这些物体是静态的(不会移动),在寻路时需要将其考虑在内。
把物体设置为“导航静态”
这里我要强调一下这个功能的强大之处。过去,和大多数游戏开发者一样,我必须自行开发寻路系统。我曾开发过A* tile和基于节点的寻路系统,在这两种系统中,尤其是基于节点的寻路系统所产生的“墙壁”问题让人十分头疼。在基于节点的寻路系统中,你必须手动设置AI导航使用的节点。而Unity的导航功能采用了导航网格(Navigation meshes),相较于手动放置节点,这种方式效率更高,路径也更流畅。更重要的是,你可以一键重新计算整个导航网格,彻底避免了手动修改导航节点的繁琐操作。
将静态物体添加到导航网格后,你可以进行一系列设置,然后点击“bake”按钮。例如,在考虑添加一堵墙之前,你可以确定斜坡的陡峭程度以及台阶的高度。这样你就能获得可预览的视图。需要注意的是,并非场景中的所有物体都自动成为导航网格的一部分。在这款游戏中,我不关心玩家是否会踩到瓦砾,因此没有将任何瓦砾标记为导航静态,这加快了导航网格的生成速度。
导航网格生成后,我只需为玩家模型添加一个NavMeshAgent组件,游戏就具备了寻路功能。接下来,只需增加鼠标输入来控制NavMeshAgent的目的地即可。
为了让NavMeshAgent进行导航,我执行了以下步骤:
- 监听鼠标输入。
- 将鼠标位置转换到屏幕空间。
- 将屏幕空间的位置转换为从摄像头发出的一束光线。
- 当光线到达地面时获取该点。
- 将NavMeshAgent的目的地设置为地面上对应的位置。
对应的C#代码如下:
// 此处应插入具体的C#代码
这样就解决了游戏的大部分导航需求,但当导航网格因游戏内的某些活动发生变化时,情况会有所不同。例如,游戏中第一个房间的门最初是关闭的,当门打开时,导航网格需要更新以反映这一变化,允许玩家从新开的门通过。我没有在游戏运行时重新烘焙完整的静态导航网格,而是使用了NavMeshObstacle组件。该组件可以将寻路过程中的动态物体添加进来,当物体移动时,Unity的寻路算法会根据实际情况进行更新。
至此,游戏的寻路导航就完成了。这就是《Arrival in Hell》游戏中导航功能的工作原理,这些操作仅需使用Unity自带的导航功能即可实现。