Unity——脚本与导航系统

news2024/11/14 14:37:57

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.coloradmin.cn/o/987293.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【postgresql 基础入门】数据库服务的管理,启动、停止、状态查看、配置加载、重启都在这里

数据库服务管理 ​专栏内容&#xff1a; postgresql内核源码分析手写数据库toadb并发编程 ​开源贡献&#xff1a; toadb开源库 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff…

【精读Uboot】反汇编分析SPL的_main函数

1、简介 典型的Uboot启动分为两个阶段&#xff0c;bootrom->SPL&#xff08;Secondary Program Loader&#xff09;->ATF->OPTEE(可选)->Uboot。其中SPL为BL2&#xff0c;ATF为BL31&#xff0c;OPTEE为BL32&#xff0c;Uboot为BL33。其中bootrom是固化在芯片内部的…

MySQL 8.0.34(x64)安装笔记

一、背景 从MySQL 5.6到5.7&#xff0c;再到8.0&#xff0c;版本的跳跃不可谓不大。安装、配置的差别也不可谓不大&#xff0c;特此备忘。 二、过程 &#xff08;1&#xff09;获取MySQL 8.0社区版&#xff08;MySQL Community Server&#xff09;   从 官网 字样 “MySQL …

3D印刷电路板在线渲染查看工具

从概念上讲&#xff0c;这是有道理的&#xff0c;因为PCB印制电路板上的走线从一个连接到下一个连接的路线基本上是平面的。 然而&#xff0c;我们生活在一个 3 维世界中&#xff0c;能够以这种方式可视化电路以及相应的组件&#xff0c;对于设计过程很有帮助。本文将介绍KiCad…

VsCode Ctrl+.修复无效

vscode 快速修复(quick fix) 快捷键(Ctrl .)被占用问题解决方法_vscode快速修复快捷键_追求者2016的博客-CSDN博客

Android 系统源码目录frameworks/base/packages和packages/apps下的APP区别

概要 在 Android Open Source Project (AOSP) 源代码中&#xff0c;frameworks/base/packages 和 packages/apps 目录都包含 Android 系统中的应用程序&#xff0c;但它们在性质和用途上有一些区别&#xff1a; 1&#xff0c;frameworks/base/packages frameworks/base 目录…

OMRON G9SP和NB触摸屏使用232口通讯

G9SP和NB触摸屏使用232口通讯 实验时间&#xff1a;2023/9/7 实验设备&#xff1a;G9SP-N20S、CP1W-CIF01&#xff08;232串口选减板&#xff09;、NB5Q-TW00B、XW2Z-200T&#xff08;串口线&#xff09;&#xff0c;CP1W-20EDT1&#xff0c;D4GS-N4T&#xff08;安全门开关&a…

alibaba国际版阿里巴巴API接入说明(阿里巴巴商品详情+关键词搜索商品列表)

API地址:https://o0b.cn/anzexi 调用示例&#xff1a;https://api-gw.onebound.cn/alibaba/item_get/?keytest_api_key& &num_iid60840463360&&langzh-CN&secret 参数说明 通用参数说明 url说明 https://api-gw.onebound.cn/平台/API类型/ 平台&#xf…

Golang 方法使用的注意事项和细节

方法的声明(定义) furie (recevier type) methodName (参数列表) (返回值列表){方法体return返回值 } 1)参数列表&#xff1a;表示方法输入 2) recevier type:表示这个方法和type这个类型进行绑定&#xff0c;或者说该方法作用于type类型 3) receiver type:type可以是结构体…

mysql 安全加固

PS&#xff1a;之前在做安全测试的时候&#xff0c;报告mysql有安全漏洞&#xff0c;于是研究了下如何修复&#xff0c;于是记录下来分享给大家 1.1修改mysql 存放位置 修复 1.停服务 service mysqld stop2.迁位置 2.1 新建迁移目录 mkdir /home/database2.2 迁移数据文件…

深入探索KVM虚拟化技术:全面掌握虚拟机的创建与管理

文章目录 安装KVM开启cpu虚拟化安装KVM检查环境是否正常 KVM图形化创建虚拟机上传ISO创建虚拟机加载镜像配置内存添加磁盘能否手工指定存储路径呢&#xff1f;创建成功安装完成查看虚拟机 KVM命令行创建虚拟机创建磁盘通过命令行创建虚拟机手动安装虚拟机 KVM命令行创建虚拟机-…

如何基于国标GB28181视频平台EasyGBS国标云服务平台建设智慧环保在线监测系统

EasyGBS平台可提供流媒体接入、处理、转发等服务&#xff0c;支持内网、公网的安防视频监控设备通过国标GB/T28181协议进行视频监控直播。基于视频图像的环保监督管理智能监控系统&#xff0c;结合了计算机技术、AI、云计算、网络传输技术和网络存储技术等先进技术&#xff0c;…

CloudQuery X PolarDB:让数据库管理更简单

前言&#xff1a;8 月 15 日&#xff0c;CloudQuery 数据操作管控平台与阿里云 PolarDB 数据库管理软件&#xff0c;完成产品集成认证测试。也在以下功能上完善了用户使用 PolarDB 的体验&#xff0c;使数据库的管理更加安全高效。 支持在 CloudQuery 中创建连接&#xff0c;便…

如何学习python?比较通义千问、文心一言、ChatGPT给的答案,你就知道啦

通义千问 通义千问是阿里巴巴达摩院自主研发的超大规模语言模型&#xff0c;能够回答问题、创作文字&#xff0c;还能表达观点、撰写代码。通义千问的能力覆盖自然语言处理的多个领域&#xff0c;包括语言理解、文本生成、代码写作等。通义千问在多项性能指标上达到了业界领先水…

springcloudSeata处理分布式事务之1.7.0

1.5.0之后版本发生了很大改变 1.seata安装 1.1官网地址 http://seata.io/zh-cn/ 1.2下载地址 https://github.com/seata/seata/releases 下载的是seata-server-1.7.0.zip 1.3seata相关配置的修改 seata-server-1.7.0\seata\conf下的application.yml进行修改 server:por…

香港服务器怎么解除被封ip?

​  解除被封IP的方法因具体情况而异&#xff0c;需要根据实际情况选择合适的解决方案。本文关于香港服务器被封IP的常见解除方法有以下步骤。 第一步&#xff1a;服务器检查 用户需要立即启动服务器进行检查。或提前申请免费试用。如果IP地址被屏蔽&#xff0c;请联系客户服…

E. Data Structures Fan(思维 + 异或前缀和)

Problem - E - Codeforces 给你一个整数数组 a1, a2,..., an&#xff0c;以及一个由 n 个字符组成的二进制字符串† s。 Augustin 是一个数据结构的爱好者。因此&#xff0c;他请你实现一个可以回答 q 个查询的数据结构。这里有两种类型的查询&#xff1a; Plain Text "1…

3次多项式轨迹规划(PLC SCL代码)

机器人、运动控制等常用的轨迹规划有三次多项式、五次多项式、梯形速度规划,S型速度规划,今天我们主要介绍三次多项式轨迹规划,有关T型和S型轨迹规划大家可以查看下面文章博客,这里不再赘述, 梯形轨迹规划 梯形速度曲线轨迹规划(速度前馈+PID、SCL+ ST代码)_RXXW_Dor的博…

c++中的list容器讲解

文章目录 1. list的介绍及使用1.1 list的介绍1.2 list的使用1.2.1 list的构造1.2.2 list iterator的使用1.2.3 list capacity1.2.4 list element access1.2.6 list的迭代器失效 2. list的模拟实现2.1 模拟实现list 3. list与vector的对比 1. list的介绍及使用 1.1 list的介绍 …

ONNX OpenVino TensorRT MediaPipe NCNN Diffusers ComfyUI

框架 和Java生成的中间文件可以在JVM上运行一样&#xff0c;AI技术在具体落地应用方面&#xff0c;和其他软件技术一样&#xff0c;也需要具体的部署和实施的。既然要做部署&#xff0c;那就会有不同平台设备上的各种不同的部署方法和相关的部署架构工具 onnx 在训练模型时可以…