薛定谔的空气墙?一文带你了解其背后的技术原理

2024-09-03 16:36

本文主要是介绍薛定谔的空气墙?一文带你了解其背后的技术原理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

封面图

悟空来了都得撞墙?

目前,被称作“村里第一个大学生”的国产3A游戏《黑神话:悟空》发售已经有一段时间了,游戏采用虚幻引擎4技术,仿佛将传统与现代的界限模糊,玩家游玩时沉浸感极强。然而,游戏也有不少令人诟病的部分,今天要说的就是网上不少人吐槽的黑神话中的“空气墙”问题

“空气墙”指的是游戏场景设计中给玩家的视觉认知与操作反馈不统一的现象,具体表现为“这里看起来明明可以通行,但走近之后却被一堵无形的墙给挡住了”。

空气墙的存在只是问题的表象,因为它往往可以用来规避更大的问题。但与一般游戏防止跌落的悬崖边空气墙不同,《黑神话:悟空》中存在很多无意义的空气墙。比如如下图模型明明有个空缺,但人物就像是一直在撞墙,一直过不去。

《黑神话:悟空》中有趣的空气墙,来源:B站up主 LaSpeeee_

如果上面的空气墙属于无伤大雅,小打小闹,那么下面这种空气墙就比较逆天了,非常折磨玩家的游玩心态。明明眼前有那么大的场景看起来可以探索,制作者还是这块台阶前铺设了一排空气墙,就连两侧的空区域也无法通行。

《黑神话:悟空》中逆天的空气墙,来源:B站up主 BlaiteHe

有玩家戏称之为“薛定谔的空气墙”。“在撞到空气墙之前,永远不知道这里是通往隐藏的小路还是空气墙。不试一下又怕错过,试了又回让人有些失望。”

越是愿意探索,空气墙的存在感就越高,也在挫败着玩家探索隐藏的欲望。

游戏中空气墙的设立不是无缘无故,制作组肯定有其含义。个人推测是《黑神话:悟空》为了各种性能优化,砍掉了原本规划的游戏路线,导致原地图可探索部分被裁剪,又临近发售,所以只能在游戏中设置了空气墙。

空气墙为何会阻止玩家前进?这就要从从游戏中的物理碰撞说起。

空气墙背后的碰撞检测

游戏引擎中物体模型和其碰撞是分开设置的,玩家前进中遇到的各种石头、树木、建筑物等障碍物之所以会阻碍玩家前进,是因为在这些模型上添加了物理碰撞。如果模型和碰撞设置的良好,当玩家刚要撞到物体模型的时候,就会因为碰撞的阻挡而停下,这种情况就给玩家一种物理的真实感。

人物与墙的碰撞测试,来源:98K物理-轻量碰撞系统

碰撞检测是游戏碰撞中的一个重要算法,它模拟了现实世界中物体之间的相互作用,也是几乎所有游戏都要用到的一个算法。比如2020年的游戏《Control》(控制)中的碰撞检测就有出色的应用。

《Control(控制)》中的物理碰撞效果,来源:B站up主 施特劳斯Woo

被称为“车祸模拟器”的物理沙盒类游戏《BeamNG.drive》在不少玩家心中拥有全球最顶尖的物理碰撞模拟和损坏效果。网上也有不少游戏与现实车祸的碰撞对比,可以看到,《BeamNG.drive》在其独特的物理引擎的加持下,具有非常拟真的碰撞效果

具备优秀物理引擎的沙盒游戏《BeamNG.drive》中的汽车碰撞效果(下)与真实碰撞(上)测试比较,来源:B站up主 依然Dy

具备优秀物理引擎的沙盒游戏《BeamNG》中的汽车碰撞效果(下)与真实碰撞(上)测试比较,来源:B站up主 依然Dy

那么,游戏中碰撞检测的背后是什么原理呢?

试想一下,一个有N个物体的场景,如果我们对这些物体每两个之间进行碰撞检测,需要的计算复杂度是O(N²) ,这对于计算机显然是不能接受的.

所以我们将碰撞检测分成两个阶段来实现,Broad-Phase(粗略检测)和Narrow-Phase(精细检测)

Broad-Phase

Broad-Phase是碰撞检测的第一个阶段,其主要目的是快速筛选出可能相互碰撞的物体对。在这个阶段,游戏引擎会使用各种空间划分技术,如AABB(Axis-Aligned Bounding Boxes,轴向包围盒)、OBB(Oriented Bounding Boxes,方向包围盒)、Sphere(球体)等,来简化物体的形状,并将这些简化后的形状存储在一个易于检索的数据结构中。

模型包围盒种类,来源:haroldserrano技术博客

常见的空间划分技术包括Uniform Grid(均匀网格)、Hierarchical Grids(层次网格)、Bounding Volume Hierarchical(BVH,包围盒层次结构)等。这些技术通过将游戏空间划分为多个子空间,并将物体分配到相应的子空间中,从而实现了对潜在碰撞体的快速筛选。

下图是以BVH为例,建立的碰撞检测流程。

碰撞检测流程,来源:haroldserrano技术博客

Narrow-Phase

在Broad-Phase初步的筛选过后,我们选出所有可能会碰撞的几何体对,Narrow-Phase的步骤是再对这些几何体进行精确的碰撞检测,比如采用凸包作为边界的体积进行碰撞检测

模型凸包边界检测,来源:haroldserrano技术博客

在物理引擎中会用到各种各样碰撞体形状,有些形状的碰撞计算非常直观且简单,比如两个球形之间,判断两个圆心的距离是否大于半径之和,就能直接计算出是否碰撞.

其余的碰撞计算就不太直观,需要一些特定的算法,但是目的都是判断两个多边形是否相交,比如在游戏引擎中比较常用的是Gilbert-Johnson-Keerthi (GJK)算法

与许多其他距离算法不同,GJK算法不要求几何数据以任何特定格式存储,而是仅依赖于一个支持函数来迭代生成更接近正确答案的单纯形,使用两个凸形状的配置空间障碍(CSO),也被称为闵可夫斯基差来判断两个形状是否有交集

闵可夫斯基差中的面-顶点(Face-Vertex)碰撞类型和边-边(Edge-Edge)碰撞类型,来源:Wiki百科

地图引擎中的碰撞检测

在地图引擎中,碰撞检测技术同样扮演了重要的角色,也是渲染性能的重要组成部分。比如在二维瓦片、三维模型渲染之前,需要对其是否可见性进行判断,判断的依据就是根据模型的外包围盒进行碰撞检测,以此只渲染屏幕看得到的模型。这样做,大大提升了渲染性能。

Mapmost中碰撞检测应用之一——模型视锥体裁剪,来源:Mapmost引擎

碰撞检测在地图中的另一个重要运用是给标注添加避让效果。通过给定每个注记外包围盒,渲染时判断这些包围盒之间的距离是否小于某个阈值,小于了就只显示唯一一个,避免多个注记的重复叠加,影响用户的使用体验。

Mapmost中碰撞检测应用之一——注记避让效果,来源:Mapmost引擎

参考文献

https://www.bilibili.com/video/BV1PMWHeHEyb/?spm_id_from=333.880.my_history.page.click&vd_source=94abb2a8fc86022a0736e7f6850b4b2f

https://www.bilibili.com/video/BV1eSWpe3EBv/?spm_id_from=333.337.search-card.all.click&vd_source=94abb2a8fc86022a0736e7f6850b4b2f

https://www.bilibili.com/video/BV1Rf4y1J7WF/?spm_id_from=333.788.recommend_more_video.0&vd_source=94abb2a8fc86022a0736e7f6850b4b2f

https://mp.weixin.qq.com/s/7OG224y-uoA8ptLWzYzXrQ

https://www.bilibili.com/video/BV1T54y1H7Dm/?spm_id_from=333.337.search-card.all.click&vd_source=94abb2a8fc86022a0736e7f6850b4b2f

https://zhuanlan.zhihu.com/p/113415779

https://en.wikipedia.org/wiki/Gilbert%E2%80%93Johnson%E2%80%93Keerthi_distance_algorithm

这篇关于薛定谔的空气墙?一文带你了解其背后的技术原理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1133457

相关文章

Java利用JSONPath操作JSON数据的技术指南

《Java利用JSONPath操作JSON数据的技术指南》JSONPath是一种强大的工具,用于查询和操作JSON数据,类似于SQL的语法,它为处理复杂的JSON数据结构提供了简单且高效... 目录1、简述2、什么是 jsONPath?3、Java 示例3.1 基本查询3.2 过滤查询3.3 递归搜索3.4

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

一文详解SpringBoot响应压缩功能的配置与优化

《一文详解SpringBoot响应压缩功能的配置与优化》SpringBoot的响应压缩功能基于智能协商机制,需同时满足很多条件,本文主要为大家详细介绍了SpringBoot响应压缩功能的配置与优化,需... 目录一、核心工作机制1.1 自动协商触发条件1.2 压缩处理流程二、配置方案详解2.1 基础YAML

Java的IO模型、Netty原理解析

《Java的IO模型、Netty原理解析》Java的I/O是以流的方式进行数据输入输出的,Java的类库涉及很多领域的IO内容:标准的输入输出,文件的操作、网络上的数据传输流、字符串流、对象流等,这篇... 目录1.什么是IO2.同步与异步、阻塞与非阻塞3.三种IO模型BIO(blocking I/O)NI

一文详解如何从零构建Spring Boot Starter并实现整合

《一文详解如何从零构建SpringBootStarter并实现整合》SpringBoot是一个开源的Java基础框架,用于创建独立、生产级的基于Spring框架的应用程序,:本文主要介绍如何从... 目录一、Spring Boot Starter的核心价值二、Starter项目创建全流程2.1 项目初始化(

一文带你了解SpringBoot中启动参数的各种用法

《一文带你了解SpringBoot中启动参数的各种用法》在使用SpringBoot开发应用时,我们通常需要根据不同的环境或特定需求调整启动参数,那么,SpringBoot提供了哪些方式来配置这些启动参... 目录一、启动参数的常见传递方式二、通过命令行参数传递启动参数三、使用 application.pro

一文带你深入了解Python中的GeneratorExit异常处理

《一文带你深入了解Python中的GeneratorExit异常处理》GeneratorExit是Python内置的异常,当生成器或协程被强制关闭时,Python解释器会向其发送这个异常,下面我们来看... 目录GeneratorExit:协程世界的死亡通知书什么是GeneratorExit实际中的问题案例

一文详解SQL Server如何跟踪自动统计信息更新

《一文详解SQLServer如何跟踪自动统计信息更新》SQLServer数据库中,我们都清楚统计信息对于优化器来说非常重要,所以本文就来和大家简单聊一聊SQLServer如何跟踪自动统计信息更新吧... SQL Server数据库中,我们都清楚统计信息对于优化器来说非常重要。一般情况下,我们会开启"自动更新

JAVA封装多线程实现的方式及原理

《JAVA封装多线程实现的方式及原理》:本文主要介绍Java中封装多线程的原理和常见方式,通过封装可以简化多线程的使用,提高安全性,并增强代码的可维护性和可扩展性,需要的朋友可以参考下... 目录前言一、封装的目标二、常见的封装方式及原理总结前言在 Java 中,封装多线程的原理主要围绕着将多线程相关的操

kotlin中的模块化结构组件及工作原理

《kotlin中的模块化结构组件及工作原理》本文介绍了Kotlin中模块化结构组件,包括ViewModel、LiveData、Room和Navigation的工作原理和基础使用,本文通过实例代码给大家... 目录ViewModel 工作原理LiveData 工作原理Room 工作原理Navigation 工