Unity——脚本与导航系统

Unity内置了一个比较完善的导航系统,一般称为Nav Mesh(导航网格),用它可以满足大多数游戏中角色自动导航的需求。


一、导航系统相关组件

Unity的导航系统由以下几个部分组成:

  1. Nav Mesh。Nav Mesh与具体的场景关联,它定义了场景中可以通过的三角面和非三角面的通路。Unity可以自动构建出Nav Mesh。
  2. Nav Mesh Agent。Nav Mesh Agent作为组件,要挂载到需要自动导航功能的角色上,它会为角色添加朝目标移动和避开障碍的功能。Nav Mesh Agent必须位于Nav Mesh之上才能发挥作用。
  3. Nav Mesh Obstacle。该组件将物体标记为障碍物,如阻碍角色行动的木桶或箱子。障碍物有两种起效的途径,一是动态障碍,让Nav Mesh Agent利用规避算法尽可能规避它;二是静态障碍,静态障碍会在Nav Mesh上挖洞,Nav Mesh Agent会围绕着这个洞修改寻路路径。如果障碍完全阻挡了路径,那么Nav Mesh Agent会去寻找一条新的路径。
  4. Off Mesh Link。某些某些通路用普通方法无法通过,但可能根据游戏设计是可以通过的。例如,一条阻断了Nav Mesh的水沟,在游戏中可以跳过去;从较低的平台无法走上较高平台,但可以通过梯子爬上去。导航系统允许在不连通的区域之间建立链接,这种链接关系通过Off Mesh Link进行标记

 解释静态、动态障碍的区别

在Unity中,静态障碍和动态障碍是指在导航系统中所采用的两种不同类型的障碍物,它们的区别主要体现在障碍物的移动性和对导航系统的影响。

1. 静态障碍(Static Obstacles):静态障碍物是指在游戏场景中位置不会发生改变的障碍物。它们通常是固定的环境元素,如墙壁、建筑物等。静态障碍物在导航系统的计算和路径规划中不会发生变化,只需要在初始化导航网格的时候标记出来即可。静态障碍物对导航系统的影响是恒定的,不会引起额外的计算开销

2. 动态障碍(Dynamic Obstacles):动态障碍物是指游戏场景中位置可能发生改变的障碍物。它们通常是动态的游戏角色、NPC、移动平台等。动态障碍物在导航系统中需要不断更新其位置信息,以便导航系统能够实时地针对它们进行路径规划。动态障碍物的移动会影响导航网格的可行走区域,导致导航系统需要重新计算路径。为了减少计算开销,Unity的导航系统提供了一些优化技术,如局部更新和动态避障等,以提高动态障碍物的移动效率和导航性能。

总结来说,静态障碍物是固定的,对导航系统没有实时的影响;而动态障碍物是可以移动的,对导航系统的计算和路径规划有实时的影响,需要特殊处理以保证角色可以正确避开它们。

二、构建导航网格 

 场景中的可移动区域一般包含了地形、平面、楼梯和斜坡等。要让导航系统自动处理这些地形,必须要事先在几何地形上搜集数据,预先计算参数,确定好导航面才可以。从几何关卡创建Nav Mesh的过程称为导航网格Bake。

 Unity有一个专门的Navigation窗口用于烘培操作,其基本的烘培操作只需以下两个步骤:

  1. 将所有场景中与导航有关的物体设置为Navigation Static。一般来说这些物体包含地形、平面、斜坡、楼梯、墙和静态障碍物,但不应包含运动的物体。选中物体后,单机Inspector右上角的小三角,打开菜单,可以看到Navigation Static选项。
  2. 打开Navigation窗口,选择主菜单的Window→AI→Navigation。然后打开其中的第三个标签页Bake,再单击下方的Bake按钮即可开始烘培。如果场景小,烘培会立即完成。烘培后可以看到但蓝色标记的可移动区域

 

有淡蓝色覆盖的部分就是可行走区域,而且仔细观察可以看到一些连线,这些连线把区域划分成了凸多边形与三角形。烘培时计算的主要信息正式这些凸多边形或三角形区域,以及每个区域与周围区域的连通关系。

导航系统的工作机制介绍:

在Unity官方文档中介绍了导航系统的工作原理,配合烘培后的网格来看不难理解。导航系统负责的工作从烘培开始,然后到具体的角色移动路线(包括移动中避障),到角色移动到目的地位置,主要分为以下4个步骤:

  1. 根据设置将地形或模型烘培,形成用很多凸多边形表示的“小平面”。这其中用到的主要算法是三角形剖分算法。
  2. 运行游戏时,在制定了起点和终点后,计算角色应当通过哪些面。这其中需要用到搜索算法,如常用的A*。
  3. 只有连通的平面的信息还不够,还需要形成具体的路线。这里的算法主要考虑的是各种拐角,尽可能按照距离最近而且平滑的路线移动,不能让角色绕得太远。
  4. 在具体移动的过程中,还需要考虑躲避动态障碍物,以及集体排队导航时互相阻挡得问题。

可以明显看到,生成的导航区域在地图边缘、墙壁边缘都有一定收缩。这是因为Nav Mesh Agent(可以理解为自动移动的角色)本身具有一定的半径,换句话说,由于角色有一定体积,角色的中心不可能紧贴在墙边。

不仅是宽度,代理得高度也会影响哪些区域能够通过,哪些不能通过,甚至斜坡的坡度、楼梯的高度也对能否通过有影响。在Bake标签页中也可以对这些参数进行设置。

1、烘培设置——导航代理的尺寸 

在导航系统的Bake标签页里,可以看到一个尺寸示意图。

虽然导航代理与场景烘培是两个不同的模块,但是Nav Mesh Agent的尺寸确实对烘培有影响,因此在烘培阶段就应该给出代理的参考尺寸。相关参数及其解释如下:

名称中文名称含义
Agent Radius角色半径代理的半径,如半径0.5m的角色无法通过宽度小于1m的通道
Agent Height角色高度代理的高度,代理无法通过低于此高度的通道
Max Slope最大坡度代理无法登上角度大于此值的坡度
Step Height台阶高度代理无法踏上高度大于此值的台阶
Drop Height最大掉落高度与自动生成导航链接有关,最大能从多高的高度跳下
Jump Distance最远跳跃距离与自动生成的导航链接有关,设定最远跳跃的距离

在修改这些参数时,既要考虑到场景尺寸,又要考虑到角色本身的尺寸,包括角色碰撞体的尺寸。通过合理的设置让可导航的路线符合游戏设计的需要,包括楼梯、坡道和通道等。

一般来说,角色的碰撞体积是用胶囊体表示的,这个胶囊体半径应该与代理半径一致或更小一些。例如,碰撞体半径大于代理半径,就可能出现导航系统认为能通过的窄路却被碰撞体阻挡的情况。再例如,角色站立时有1.8m,下蹲后可以通过0.9m的小洞,那么导航参数夜莺岛考虑到角色下蹲移动的情况。

2、烘培数据文件

当烘培完成后,再场景所在文件夹下,会多出一个与场景名称相同的文件夹,文件夹中有一个NavMesh.asset文件,里面就是烘培保存的数据了。

三、创建导航代理

烘培好Nav Mesh后,就可以添加Nav Mesh Agent了。Nav Mesh Agent也是一个组件,它可调整的参数比较多。下面先做一个可以随鼠标点击移动的例子。

  1. 创建一个胶囊体代表玩家,紧贴底面(已经烘培好的导航面)放置。
  2. 给胶囊体添加Nav Mesh Agent组件,默认参数即可。
  3. 创建脚本MoveTo,让物体向鼠标点击的位置移动。
  4. 将脚本挂载到胶囊提上,将摄像机升高并低头,改为半俯视角。
  5. 运行游戏,通过鼠标左键单击地面,胶囊体会朝着目标寻路移动。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class MoveTo : MonoBehaviour
{UnityEngine.AI.NavMeshAgent agent;void Start(){agent = GetComponent<UnityEngine.AI.NavMeshAgent>();}void Update(){if(Input.GetMouseButtonDown(0)){Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);RaycastHit hit;if(Physics.Raycast(ray,out hit)){agent.destination = hit.point;}}}
}

在运行游戏的同时打开导航烘培窗口,可以一边观察导航网格一边测试游戏,从而方便观察前往不同目的地的导航效果差异。特别是当单机没有被导航网格覆盖的白色区域时,物体依然会尽可能靠近目的地,停留在接近目的地的位置。

以上脚本通过摄像机发射射线,得到鼠标单击的位置。其操作导航代理的关键代码只有一条,如下所示:

agent.destination=hit.point;

只要设置了目的地,导航就会自动朝目标移动。

关于Nav Mesh Agent组件还有很多值得说明的参数和使用方法。下面先介绍Nav Mesh Agent组件的参数,再介绍Nav Mesh Agent组件的常用属性。

参数

说明名称中文名称说明
位置Base Offset中心偏移代理中心与物体中心点的y轴偏差距离。由于代理会自动贴在导航面上移动,如果有偏差就需要调节这个值。

Steering

(运动和

 转向)

Speed移动速度导航移动的速度受到此参数限制
Angular Speed角速度导航移动的转身速度
Acceleration加速度模拟角色由慢到快的加速度
Stopping Distance停止距离当离目标的距离小于此值时,就算到达了。此值控制允许误差的范围
Auto Braking自动刹车减速效果

Obstacle

Avoidance

(躲避障碍)

Radius避障半径躲避障碍时的自身半径参考值,较大的值代表尽可能远离障碍
Height避障高度避障时自身高度的参考值
Quality避障品质可调节避障算法的精度。精度越高,效果越好,对性能的影响也就越大
Priority避障优先级当多个代理一起避障移动时,数值小的代理优先级更高

属性

属性类型用途
hasPathbool当前是否有路径。也可以根据它判断是否到达目的地
isStoppedbool设置为true可以终止寻路
pathNavMeshPath获得当前路径对象
speedfloatNav Mesh Agent组件设置的速度,其他参数也可以用脚本控制
AngularSpeedfloatNav Mesh Agent组件设置的角速度
remainingDistancefloat当前位置到终点的位置
destinationVector3终点位置,设置它可以启动寻路
stoppingDistancefloatNav Mesh Agent组件的停止距离(即误差距离)
isOnNavMeshbool是否处于导航面上
velocityVector3代理当前实际运动的速度向量,非常有用的属性

以上属性都可以通过脚本读取或设置

四、导航障碍物

静态障碍物,如墙、水沟可以在烘培时就处理好,而在场景中动态添加的障碍物就无法预先烘培了。Nav Mesh Obstacle组件正是为标记动态障碍物而生的。其属性如图所示。

Nav Mesh Obstacle组件刻修改的参数不多,简单调整后即可使用。

障碍物的形状只有Box与Capsule两种。由于Nav Mesh Agent组件也有一定体积,因此没有必要定义精确的形状。选择形状后可以分别对位置、大小和半径等参数进行提及设置。

障碍物的存在会对导航产生影响,可选两种影响方式:阻碍和打洞。不勾选Carve选项就是阻碍,反之是打洞。

阻碍方式对导航层本身没有影响,就像是地图上的普通障碍物一样,Nav Mesh Agent组件会用规避算法尽量规避障碍物。阻碍方式的优点是不影响导航层,没有重新计算导航层的性能开销;缺点是规避效果取决于Nav Mesh Agent组件的具体移动,当障碍物较多、障碍物体积较大时,避障效果可能不会太理想。

打洞方式则会影响导航层本身的信息,就像是障碍物呗烘培到导航层上一样。Nav Mesh Agent组件在计算路径的阶段就会避开有洞的位置。

可以创建两个Nav Mesh Obetacle,测试勾选或不勾选Carve的效果。如图,上边是勾选的,下面是没有勾选的。

在开启导航窗口的情况下,两个Nav Mesh Obstacle的影响的区别显而易见。如果移动设置为打洞的那个障碍物,导航层会随之变化。

阻碍方式对性能影响较小,适合有一定运动速度、体积不太大的物体。打洞方式会引起导航层局部从新计算,带来一定的性能开销,因此适合于静态的、长期的地形变化。

例如,游戏中道路被掉落的石块堵死,适合用打洞方式实现;而角色过马路时路上的汽车等运动的小障碍,适合用阻碍方式实现。

下面介绍一下自动打洞设置。

在实际游戏中,障碍物的情况可能介于"快速变化"与"静止不变"之间,因此障碍物还支持更细节的控制。通过判断物体移动的距离和静止不动的时间,来确定打洞的时机,这一功能是通过Move Threshold(移动阈值)、Time To Stationary(固定时间)和Carve Only Stationary(仅固定时打洞)3个参数实现的。简单来说,在勾选了Carve Only Stationary的前提下,当物体移动距离超过了Move Threshold的值则取消打洞;当物体的静止时间超过了Time To Stationary的值,就可以被看作暂时固定,切换到固定状态时会进行打洞。

以上参数用文字解释比较抽象,有一个好方法可以快速直观测试这些参数的作用。

  1. 在一个烘培好的地形上放置两个导航障碍物,其中一个设置为打洞模式并勾选Carve Only Stationary,另一个设置为阻碍模式作为对照。
  2. 运行游戏,在场景中移动打洞障碍物的位置,当速度高于某个值时,导航的孔洞就会消失;当物体静止以后再经过一点时间,孔洞又会出现。这里的速度阈值和静止时间正是由Move Threshold和Time To Stationary分别控制的。

这些参数与实际游戏设计相关,只有在实际游戏开发中遇到了性能问题再仔细调整。通过这些参数可以控制大东的频率,平衡性呢个与导航效果之间的矛盾。

五、导航链接

游戏中的角色不仅会平面移动、爬楼梯和斜坡,有时还会跳跃,甚至瞬间移动。一旦有跳跃等情况,直接结果就是导航中会出现一些特例。第一种情况是走捷径,如角色不用走楼梯下楼,直接从二楼跳下更快。第二种 情况是直接跨越两个独立的导航面,走过导航面不连通的路径。

这种在原有导航面基础上添加的路径或捷径就是导航链接。如Unity支持自动生成导航链接和手动生成导航链接,下面分别简述其制作方法。

 1、自动生成导航链接

自动生成导航链接非常容易,先将所有静态导航物体设置为“可生成链接”,再在烘培窗口中设置角色的最大下落高度、最大跳跃距离,最后重新烘培即可,其具体操作如下。

  1. 打开Navigation窗口的Object标签页这个页面实际上是一个场景物体的过滤器,方便过滤和选择物体,如筛选所有具有网格渲染器的物体或所有具有地形组件的物体。无论是否过滤,只要在场景中选中所有需要生成导航链接的物体即可。例如,可以将前面所有设置为Navigation Static的物体选中,然后再在标签页中勾选Generate OffMeshLinks
  2. 完成之后回到Bake标签页,设置角色最大Drop Height和最远Jump Distance。为了效果明显,可以将它们的值设置得大一些
  3. 完成之后再次烘培,烘培结果中会出现很多小箭头,每个箭头都代表着一处导航链接。

 2、手动生成导航链接

自动生成导航链接很方便,但不易控制,很容易生成大量链接。如果仅在个别地方需要链接,建议手动生成导航链接。手动操作的方法很简单,步骤如下:

  1. 为了方便起见,新建一个空物体,位置归0
  2. 新建两个物体作为其子物体,这里分别命名为NodeA和NodeB
  3. 给父物体添加Off Mesh Link组件,Start设置为NodeA,End设置为NodeB
  4. 完成之后只要修改物体NodeA和NodeB的位置,就可以控制导航链接的位置了。为了方便查看和修改,可以在移动物体时打开Navigation窗口,这样就可以看到表示链接的箭头

这样生成的链接,使用时与自动生成的链接没有区别。

Off Mesh Link组件还有一个Bi Directional选项。勾选它表示既有正向链接也有反向链接,不勾选代表单向链接,只能从起点到终点,不能返回。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/125076.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows Qt 5.12.10下载与安装

Qt 入门实战教程&#xff08;目录&#xff09; C自学精简教程 目录(必读) 1 Qt下载 qt-opensource-windows-x86-5.12.10.exe 官方离线安装包&#xff1a;Download Source Package Offline Installers | Qt 下载巨慢 只能下载到最新的&#xff1a;https://download.qt.io/a…

JVM | 垃圾回收器(GC)- Java内存管理的守护者

引言 在编程世界中&#xff0c;有效的内存管理是至关重要的。这不仅确保了应用程序的稳定运行&#xff0c;还可以大大提高性能和响应速度。作为世界上最受欢迎的编程语言之一&#xff0c;通过Java虚拟机内部的垃圾回收器组件来自动管理内存&#xff0c;是成为之一的其中一项必…

Speech | 语音处理,分割一段音频(python)

本文主要是关于语音数据在处理过程中的一些脚本文件以及实例&#xff0c;所有代码只需要更改所需处理的文件路径&#xff0c;输出路径等&#xff0c;全部可运行。 目录 所需环境 方法1&#xff1a;将一整段音频按时间批量切成一个一个音频 方法2&#xff1a;将一整段音频按…

C++的类型转换

前言 我们都知道C是兼容C语言的在C语言中存在两种方式的类型转换&#xff0c;分别是隐式类型转换和显示类型转换&#xff08;强制类型转换&#xff09;&#xff0c;但是C觉得C语言的这套东西是够好&#xff0c;所以在兼容C语言的基础上又搞了一套自己的关于类型转换的东西。 目…

2023高教社杯数学建模C题思路代码 - 蔬菜类商品的自动定价与补货决策

# 1 赛题 在生鲜商超中&#xff0c;一般蔬菜类商品的保鲜期都比较短&#xff0c;且品相随销售时间的增加而变差&#xff0c; 大部分品种如当日未售出&#xff0c;隔日就无法再售。因此&#xff0c; 商超通常会根据各商品的历史销售和需 求情况每天进行补货。 由于商超销售的蔬菜…

mysql创建用户

创建用户 创建 -- 创建用户 itcast , localhost只能够在当前主机localhost访问, 密码123456; create user test01localhost identified by 123456;使用命令show databases;命令&#xff0c;只显示一个数据库&#xff0c;因为没有权限 -- 创建用户 test02, 可以在任意主机访问…

Stream API

Stream API执行流程 Stream API(java.util.stream)把真正的函数式编程风格引入到Java中,可以极大地提高程序员生产力&#xff0c;让程序员写出高效、简洁的代码 实际开发中项目中多数数据源都是来自MySQL、Oracle等关系型数据库,还有部分来自MongDB、Redis等非关系型数据库 …

vue3路由跳转params传参接收不到

import { useRouter } from "vue-router";const router useRouter(); // 提现记录 const withdrawalClick (item) > {router.push({ name: "Devwithdrawal", params: { name: 123 } }); };//跳转页面接收参数 import { useRoute } from "vue-rou…

网络是如何进行通信

网络是如何进行通信的 简介 在现代社会中&#xff0c;网络已经成为我们生活中不可或缺的一部分。从上网搜索信息、在线购物到远程工作和社交媒体&#xff0c;我们几乎无时无刻不与网络保持着联系。但是&#xff0c;网络究竟是个什么玩意&#xff0c;它是如何工作的呢&#xf…

Web服务器简介及HTTP协议

一、Web Server&#xff08;网页服务器&#xff09; 一个 Web Server 就是一个服务器软件&#xff08;程序&#xff09;&#xff0c;或者是运行这个服务器软件的硬件&#xff08;计算机&#xff09;。其主要功能是通过 HTTP 协议与客户端&#xff08;通常是浏览器&#xff08…

python可视化模块—快速利用matplot绘制图表

文章目录 一、Matplotlib基本介绍二、两种绘图方式区别&#xff08;plt.*** 和ax.***&#xff09;三、如何使用Matplotlib绘图1、画布—绘画的画板2、配置—更个性化的绘图全局配置局部配置面向对象绘图过程&#xff1a;ax代表子图变量过程式绘图过程 四、常用绘图图形如何选择…

配电房能源监测系统

配电房能源监测系统是一种能够实时监测和管理配电房能源消耗的系统&#xff0c;有助于企业更好地管理能源使用&#xff0c;降低能源成本&#xff0c;提高能源利用效率。本文将详细介绍配电房能源监测系统的组成、功能和优点。 一、配电房能源监测系统的组成 配电房能源监测系统…

网络通信深入解析:探索TCP/IP模型

http协议访问web 你知道在我们的网页浏览器的地址当中输入url&#xff0c;未必是如何呈现的吗&#xff1f; web浏览器根据地址栏中指定的url&#xff0c;从web服务器获取文件资源&#xff08;resource&#xff09;等信息&#xff0c;从而显示出web页面。web使用HTTP&#xff08…

OpenHarmony 使用 ArkUI Inspector 分析布局

● 摘要&#xff1a;视图的嵌套层次会影响应用的性能&#xff0c;开发者应该移除多余的嵌套层次&#xff0c;缩短组件刷新耗时。本文会介绍如何使用 ArkUI Inspector 工具分析布局&#xff0c;提示应用响应性能。 ● 关键字&#xff1a;列举本文相关的关键字&#xff1a;OpenH…

vue3:3、项目目录和关键文件

关于vsvode的更改 <!-- 加上setup允许在script中直接编写组合式api --> <script setup> // 组件引入后直接用 import HelloWorld from ./components/HelloWorld.vue import TheWelcome from ./components/TheWelcome.vue</script><!-- 1、js放在最上面&am…

Mavan进阶之多模块(聚合)

文章目录 Maven 多模块&#xff08;聚合&#xff09;非父子关系的多模块项目 Maven 多模块&#xff08;聚合&#xff09; Maven 继承和聚合是 2 个独立的概念。工程与工程之间可能毫无关系&#xff0c;也可能是继承关系&#xff0c;也可能是聚合关系&#xff0c;也可能既是继承…

美客多选品趋势分析,美客多选品时的注意事项

都知道选品的重要性&#xff0c;美客多这个平台也一样&#xff0c;选品选对了肯定事半功倍&#xff0c;本文介绍了美客多选品趋势分析&#xff0c;美客多选品时的注意事项&#xff0c;一起来了解下吧。、 美客多选品趋势分析 1、墨西哥站&#xff1a;跨境支付高&#xff0c;偏…

CSS---flex布局

主要记录flex布局的要点以及实例 flex flex父标签的6个属性flex-direction: flex布局的方向flex-wrap: 是否可以换行flex-flow: flex-direction 和 flex-wrap 一起写justify-content&#xff1a;横向对齐方式align-items: 纵向对齐方式align-content: 有换行情况下的纵向对齐方…

【MySQL系列】MySQL的事务管理的学习(一)_ 事务概念 | 事务操作方式 | 事务隔离级别

「前言」文章内容大致是MySQL事务管理。 「归属专栏」MySQL 「主页链接」个人主页 「笔者」枫叶先生(fy) 目录 一、事务概念二、事务的版本支持三、事务提交方式四、事务常见的操作方式4.1 事务正常操作4.2 事务异常验证 五、事务隔离级别5.1 查看与设置隔离性5.2 读未提交&…

jmeter 准确的吞吐量定时器 Precise Throughput Timer

准确的吞吐量定时器使用实例 提取码&#xff1a;gpex&#xff1a; 说明&#xff1a;配置10个线程&#xff0c;每个线程请求200次&#xff0c;通过准确地的定时器模拟QPS为20的场景 配置测试接口参考链接 配置jmeter测试脚本&#xff0c;主要关注准确的吞吐量定时器参数配置 目…