首页 统一教程

导航网格寻路:入门

游戏中的角色通常需要在关卡中的障碍物周围导航。由于这是游戏中的常见情况,因此Unity提供了一个内置的寻路解决方案,称为NavMesh。在本教程中,您将使用NavMesh实现点击移动。

5/5 2个评分

  • C#7.3,Unity 2020.1,Unity

游戏中的角色通常必须绕过障碍物。考虑一下尝试在迷宫中跟随玩家的坏人。这个问题的技术术语是 寻找路径。这是计算机需要计算字符移动路径的地方。由于这种情况经常在游戏中出现,因此Unity提供了一种内置的寻路解决方案,称为 导航网格.

在本教程中,您将学习:

    • 游戏使用的寻路方法
    • 如何使用Unity的寻路技术NavMesh
    • 调整或自定义NavMesh导航的方法

为了获得一些动手练习,您将使用Unity的NavMesh寻路实现点击动作。通过单击,在本教程的顶部或底部下载项目文件。 下载资料 按钮。该示例项目使用Unity 2020.1.17并提供了示例场景,因此您可以专注于寻路功能。

注意:这是一个中级教程,假定您已经了解如何操作Unity的基础知识。如果您不熟悉Unity,请先从我们的 统一简介:入门 教程。

游戏中的寻路

游戏中的AI角色通常必须找到到达目的地的最佳途径。您可以从几种算法中进行寻路,但是A *在除少数特殊情况以外的所有情况下都是不错的选择。

A *(或A星)

在各种计算环境中,A *算法通常用于寻路-它并非特定于Unity。甚至还有 本网站上的A *文章,在iOS开发的背景下讨论了该算法。为了更深入的了解, 本文 提供了该算法的图解交互式指南。 这个 说明了独立于任何特定技术堆栈的步骤。

本教程此处不会详细解释A *,因为您可以阅读这些出色的解释。相反,这是Unity的寻路方法的正确选择!

导航网格

前面提到的A *文章讨论了在正方形网格上的寻路,但是该算法不需要这样的地图。 A *也可以与其他形状配合使用!该算法所需的全部只是连接节点的图,而正方形网格只是这样的一个图。您甚至可以将A *与现实世界的地图一起使用:道路的交叉点是节点,道路是节点之间的连接。

游戏通常用网格表示寻路图。也就是说,就像3D模型一样,用于寻路的图形可以 用由边连接的顶点表示。这样的网格称为 导航网格, so 统一’s tech for this has the abbreviated 名称 导航网格.

统一内置了基本的NavMesh功能,但通过以下方式提供了更强大的网格生成和寻路功能 一个开源项目导航网格组件。设置自己的项目时,可以从该GitHub存储库下载这些组件。但是它们已经包含在启动项目中。现在,该讨论如何使用这些组件了!

入门

为了充分利用NavMesh组件,您将开发一个简单的点击运动演示。角色将移动到被点击的位置,就像点击冒险游戏一样。借助NavMesh的功能,角色甚至可以知道如何避开障碍物。

您的角色需要一个场景来跑来跑去,并需要一些障碍物来导航。幸运的是,入门项目提供了这些。导航 资产/ RW /场景 并打开 SampleScene。该场景仅具有一堆用于墙壁和地板的块,以及一个用来代表玩家的胶囊。

设置好导航级别后,您已经具有构建导航网格所需的功能!

生成导航网格

First, create an empty GameObject 和 名称 it 导航网格。导航网格将由此对象生成并附加到该对象。现在,添加一个 导航网格表面 此对象的组件。在检查器中,现在有许多导航设置,以及几个用于管理网格生成的按钮。

就是这样-您已经准备好创建第一个网格!请点击 ,然后Unity使用默认设置生成导航网格物体。

带有烘焙网格的场景视图

您的第一个烤网!

了解NavMeshSurface

发生了什么?底层代码非常复杂,但是主要步骤并不难理解。 导航网格表面 首先使用自己的GameObject的旋转角度来决定向上的方向。然后,它确定场景中面向该方向的表面。 (在这种情况下,它们都是扁平的,但是 导航网格表面 也适用于地形和其他不规则网格。)

然后,NavMesh系统必须确定每个表面的哪些部分是可步行的。游戏角色具有各种形状和大小。例如,猫咪可以走路的区域与人类或巨型机器人可以走路的区域不同。这是顶部图 导航网格表面 进来。

导航网格表面中显示的代理设置图

它看起来像是数学课上的笔记,但这是您的NavMesh代理设置。

该图说明了将在此网格上行走的特定类型的代理的属性,例如其半径和高度。 (您可以在 代理商类型 下拉菜单(如果需要),但本教程不需要它们。)

导航网格系统使用这些设置来确定该代理可以到达的位置。当系统找到足够平坦,宽且足够高的区域用于此类代理程序时,它将将该区域标记为可步行。然后,它生成一个平面导航网格-刚出现在场景中的蓝色区域。

现在,您已经烤好了网格,是时候更仔细地查看结果了。默认设置工作得很好,但是总有一些需要调整的地方。

使用图层调整NavMesh

首先,播放器周围的网格中有一个洞。默认情况下,场景中的所有内容都被视为潜在的导航障碍。您需要明确告诉 导航网格表面 不要把玩家当作障碍。

导航网格表面 有一个名为 包括层。如果在该下拉菜单中取消选择层,则网格生成系统将忽略该层上的对象。请按照以下步骤将播放器放置在新层上,然后从网格中排除该层:

  1. 选择 播放器 中的GameObject 层次结构.
  2. 在里面 下拉菜单,选择 添加图层.
  3. 在里面 layer management view that appears, type the 名称 播放器 在第一行。
  4. 再次选择播放器。使用 下拉菜单,将其图层更改为新创建的图层 播放器 层。 (如果遇到其他挑战,可以快五倍对自己说“玩家层”。)
  5. 出现一个弹出窗口,询问是否也将子对象分配给该层。选择 是的,换孩子.
  6. 选择 导航网格.
  7. 在检查器中,打开 包括层 下拉菜单,然后单击 播放器 取消选择。
图层下拉菜单

从此下拉菜单中为播放器创建一个图层,然后为其分配一个图层。

现在,Unity将了解该播放器不是场景的一部分。请点击 重新生成导航网格。不再有孔!

从NavMesh移除对象

但是还有另一个问题。用 导航网格 仍处于选中状态,请查看大的角块。顶部的蓝色方块表示导航系统将其视为地板的一部分-也就是说,可以是有效路径一部分的表面。播放器应该只能在地板上行走,不能在墙壁上行走!但是您不能像使用播放器那样忽略该障碍。它仍然需要成为一个障碍,以便NavMesh不会生成通过它的路径。

幸运的是,您可以使用另一个名为 导航网格修改器。设置步骤如下:

  1. 看看...的孩子 迷宫 然后选择 .
  2. 添加一个 导航网格修改器 零件。
  3. 在组件上,单击以启用 覆盖区域.
  4. 更改 区域类型不可步行.
导航网格修改器组件中的“覆盖区域”设置

导航网格修改器组件中的“覆盖区域”设置

现在,Unity了解到 是障碍物,而不是可行走的表面。请点击 导航网格 然后再次烘烤导航网格。问题解决了!

没有NavMesh的角块

只是普通的墙而已。

通过这些调整,您可以正确设置导航。您已经准备好让玩家在迷宫中四处奔走!

移动角色

在导航网格上移动对象是任务 导航网格代理 零件。它会计算沿网格从当前位置到您指定的目标位置(或最接近的点,如果不在网格上)的路径。

设置NavMeshAgent组件

首先,选择播放器并添加一个 导航网格代理 零件。

座席动作的默认设置有些迟缓,但是您可以对其进行调整以使其更加灵活。上 导航网格代理, 增加 速度5, 角速度360加速10.

导航网格代理组件中的转向设置

导航网格代理组件中的转向设置

现在,您只需要一个脚本来设置 导航网格代理的目的地,剩下的就由NavMesh负责!

设置NavMeshAgent的目的地

创建一个名为的新C#脚本 播放器Movement.cs 在里面 资产/ RW /脚本 目录。在类的顶部,类定义上方添加此要求:

using 统一Engine.AI;

该库使NavMesh类可用。

接下来,在类的顶部声明这两个变量:

private Camera cam;
private 导航网格代理 agent;

Add these lines 至 Start:

cam = Camera.main;
agent = GetComponent<NavMeshAgent>();

The Camera class has a convenient method that translates the mouse’s location on the screen 至 a position 在里面 game world. Pass that position 至 agent as its destination.

Add the following 至 Update :

if (Input.GetMouseButtonDown(0))
{
    Ray ray = cam.ScreenPointToRay(Input.mousePosition);

}

This code checks each frame 至 see if the mouse button is pressed. If so, it constructs a Ray from the camera 至 the mouse’s position. You’ll use the ray 在里面 next step.

Next, add these lines inside the if statement, after creating the ray:

if (Physics.Raycast(ray, out RaycastHit hit))
{
    agent.SetDestination(hit.point);
}

This code sends the ray out into the game world 和 checks whether it hits anything. (Note that the ray will only hit objects 具有 colliders.) If the ray does hit something, it will store the location of the hit in hit.point. Then, you can simply give that location 至 agent as its destination.

将此脚本拖到播放器对象上,然后按 。在迷宫中的任意位置单击,播放器就会移动到您单击的位置!玩家在迷宫般的墙壁周围导航以到达目的地。

完善导航网格

现在角色已成功在迷宫中移动,您可以通过指定导航使导航网格更加有趣 地区费用。当您将角块设置为时,您实际上已经调整了一个导航区域 不可步行。但是您不仅可以打开和关闭区域,还可以做更多的事情。

为了代表更复杂的环境,您可以指定不同的 地区 具有 费用 —权重定义该区域移动的难易程度(或不理想)。 导航网格代理将倾向于避开高成本区域,即使在技术上跨该区域的路径较短。想想军事单位越过地形变化的情况:如果他们穿过山脉,路径可能会更短,但是他们更喜欢通过空旷的地方绕过山脉。使用导航网格中各种成本的区域来表示这种情况很简单。

在示例场景中,请注意地板的一块是蓝色。您可以在那里分配一个单独的导航区域,以模拟导航代理将避免的水域。

分配导航区域

首先,在导航系统中添加一个新区域。选择 视窗▸AI▸导航 打开项目导航设置。然后,选择 地区 tab 至 see all the navigation 地区 defined in this project. Type the 名称 在第一行中并将其费用设置为 5.

导航窗口的区域选项卡

导航窗口的区域选项卡中的区域和成本列表

返回到“场景”视图。看看...的孩子 迷宫 然后选择 。 (如果它位于导航后面,则可能需要选择“检查器”选项卡才能再次查看。) 导航网格修改器 组件,打开 覆盖区域 并改变 区域类型。然后再次烘烤网格。

导航网格具有紫色区域

导航网格,水域以紫色显示

然后在网格物体上单击以查看玩家的寻路方式是如何变化的。例如,尝试将播放器放在右上角,然后单击角落块正下方。到达此目的地的最短路径将穿过水域。取而代之的是,玩家在很长的一段距离内导航。

导航网格寻路避免高成本导航区域的示例

将播放器放在右上角,然后单击X所在的位置。

然后去哪儿?

通过单击下载完整的项目文件 下载资料 本教程顶部或底部的按钮。

您现在知道在Unity中使用NavMesh进行寻路的基本知识!记住三个主要组成部分: 导航网格表面, 导航网格修改器导航网格代理.

导航网格系统可以做很多事情。您可以使用 导航网格代理 设置,创建在墙壁或天花板上行走的角色,或探索将多个网格物体链接在一起。或者,您可以接下来尝试运行时生成。 “运行时生成”是指在游戏运行时创建导航网格,而不是像本教程中那样提前烘焙一个。

尽管NavMesh是免费的并且运行良好,但是许多开发人员更喜欢 A *寻路项目。如果您的游戏需要寻路,也请检查一下。

希望您喜欢本教程!如果您有任何问题,意见或建议,请随时将它们留在下面的评论中或访问我们的论坛。

平均评分

5/5

为此内容添加评分

2个评分

更像这样

贡献者

评论