12.Unity导航系统

12.Unity导航系统

首页休闲益智跳跃网格更新时间:2024-07-01
12.导航系统12.1 导航网格

导航网格指的是游戏场景中可以通过的区域。在 Unity 中,我们只需要指定场景中哪些游戏对象参与导航网格的计算,就可以自动生成导航网格。

生成导航网格的步骤:

1.选中所有参与计算的游戏对象,在 Inspector 视图中展开 Static 下列列表选中 Navigation Static 选项。

2.执行菜单:Window -> AI -> Navigation ,打开 Navigation 面板。在该面板中的有 4 个选项卡分别是:Agents、Areas、Bake、Object,选中 Bake 选项卡,单击 Bake 按钮。

3.Bake 完成后在场景中会出现 Bake 网格,网格内的区域就是允许导航的区域。如下图所示:

Bake 属性如下:

12.2 导航代理

导航代理是一个独立的组件,给游戏角色添加 Nav Mesh Agent(导航网格代理)组件后,角色就会在导航区域中进行导航移动。

Nav Mesh Agent 组件属性:

使用脚本控制导航:

当场景中导航网格已经生成,游戏角色也挂载了导航代理组件后,接下来就可以为游戏角色添加脚本,在脚本中控制导航进行移动。

示例:单击场景中的位置作为目标点,使角色朝目标点移动,并最终到达目标点。代码如下:

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class PlayerController : MonoBehaviour { private NavMeshAgent _agent; // Start is called before the first frame update void Start() { _agent = GetComponent<NavMeshAgent>(); } // Update is called once per frame void Update() { if (Input.GetMouseButtonDown(0)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; bool res = Physics.Raycast(ray, out hit); if (res) { Vector3 point = hit.point; _agent.SetDestination(point); } } } }12.3 障碍物

在导航网格生成时,静态障碍物会自动生成好,但在游戏中经常会遇到动态障碍物,对于动态障碍物,需要使用 Nav Mesh Obstacle(导航网格障碍)组件。

Nav Mesh Obstacle 组件属性:

在添加障碍物时,除了要挂载 Nav Mesh Obstacle 组件外,还要为障碍物物体取消勾选 Static 选项。

示例:通过障碍物控制胶囊体移动。

1.新建项目,在场景中添加一个 Plane,缩放为 (2,2,2),添加一个胶囊体,命名为 NPC,并给 NPC 添加 Nav Mesh Agent 组件。

2.在 Project 视图中创建脚本 NPCController,并挂载到 NPC 物体上,代码如下:

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class NPCController : MonoBehaviour { // 导航代理组件 private NavMeshAgent _agent; // 目标点 private Vector3 targetPosition; // 是否到达目标点 private bool isArrived = false; // Start is called before the first frame update void Start() { _agent = GetComponent<NavMeshAgent>(); targetPosition = transform.position new Vector3(0, 0, 10); _agent.SetDestination(targetPosition); } // Update is called once per frame void Update() { // 获取距离目标点的距离 float dis = Vector3.Distance(transform.position, targetPosition); if (_agent.remainingDistance < 0.1f) { // 在与目标点的距离小于 0.1 的情况下 if (isArrived) { // 在开始位置 isArrived = false; // 向终点移动 targetPosition = transform.position new Vector3(0, 0, 10); } else { // 在终点位置 isArrived = true; // 向开始点移动 targetPosition = transform.position - new Vector3(0, 0, 10); } _agent.SetDestination(targetPosition); } } }

3.选中 Plane,执行 Window -> AI -> Navigation ,在 Inspector 视图中勾选 Navigation Static,单击 Bake 选项卡,单击 Bake 按钮。

4.在场景中添加立方体,命名为 Player,位置为(-0.15,1,-3),缩放为(8,2,0.4),给 Player 添加 Nav Mesh Obstacle 组件。

5.在 Project 视图中创建脚本 PlayerController,并挂载到 Player 上,代码如下:

using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerController : MonoBehaviour { // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { float h = Input.GetAxis("Horizontal"); transform.position = transform.right * h * 0.3f; } }

运行游戏,我们会发现,无论怎么样移动障碍物,NPC 都会自动躲避障碍物。

12.4 导航网格链接

网格之间可以设置网格链接。在导航网格生成时,Bake 选项卡中的 Generated Off Mesh Links 中包括 Drop Height(掉落高度)和 Jump Distance(跳跃距离),这个两个属性运行从高台掉落并在高台间跳跃。同时,选中场景中的高台物体(一个或多个),在 Object 选项卡中勾选 Generate Off Mesh Links 选项,然后再在 Bake 选项卡中单击 Bake 按钮,Bake 完成后,可以看到高台的附加自动生成链接,这样角色就可以在链接之间移动了。

上面我们说明的是通过 Bake 自动生成导航网格链接,在实际开发中,我们会需要自己控制网格间的链接,也就是说,我们希望能从某点到另外一点生成一个链接。这时,就需要用到 Off Mesh Link 组件。

Off Mesh Link 组件属性:

Start - 网格链接起始位置的游戏物体。

End - 网格连接结束位置的游戏物体。

Cost Override - 网格链接花费的成本。

Bi Directional - 是否允许双向移动。

Actived - 是否已激活该网格链接。

Auto Update Positions - 是否自动更新位置,勾选后,当起始或结束位置的对象移动时,会更新网格链接。

Navigation Area - 导航区域,网格链接属于的导航区域。

创建网格链接的步骤:

创建一个平面,缩放为(0.03,0.03,0.03),复制一份,并将两个平面放在希望进行网格链接的两个位置。

选择其中一个添加 Off Mesh Link 组件,然后将两个平面分别放在组件的 Start 和 End 处。即可看到生成的网格链接,如下图所示:

12.5 导航区域

在 Navigation 面板上,Areas 选项卡中,一共可以设置 32 个区域,默认设置了 3 个区域,其余区域可以自定义,每个区域都会有颜色和成本的设置。

成本的含义为导航代理网格移动时消耗的体力,导航系统在计算推荐路线时会将成本计算在内。

示例:让胶囊体在规划的路线上移动。

1.新建项目,并在场景中添加 1 个 平面和 8 个 立方体(路面)、1 个胶囊体(角色),形成如下图所示场景:

2.打开 Navigation 面板(Window -> AI -> Navigation),单击 Areas 选项卡,增加一个 Road 区域,设置成本为 1,Walkable 成本为 100。

3.单击一个立方体,在 Navigation 面板中的 Object 选项卡这设置 Navigation Area 为 Road(其他立方体也是如此)。

4.选择 1 个 平面和 8 个 立方体,在 Navigation 面板中 Bake 选项卡中单击 Bake 按钮,完成后如下图所示:

5.在 Project 视图中创建脚本 PlayerController,挂载到胶囊体,代码如下:

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class PlayerController : MonoBehaviour { private NavMeshAgent _agent; // Start is called before the first frame update void Start() { _agent = GetComponent<NavMeshAgent>(); } // Update is called once per frame void Update() { if (Input.GetMouseButtonDown(0)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; bool res = Physics.Raycast(ray, out hit); if (res && hit.collider.gameObject.name != "Plane") // 只能在非 Plane 上移动 { Vector3 point = hit.point; _agent.SetDestination(point); } } } }

运行游戏,看看效果,应该是只有在单击立方体时才会移动,移动时是沿着立方体的表面移动的,而不会走 Plane 绿色的区域。

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved