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

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获取PDF页面信息

《一文详解如何使用Java获取PDF页面信息》了解PDF页面属性是我们在处理文档、内容提取、打印设置或页面重组等任务时不可或缺的一环,下面我们就来看看如何使用Java语言获取这些信息吧... 目录引言一、安装和引入PDF处理库引入依赖二、获取 PDF 页数三、获取页面尺寸(宽高)四、获取页面旋转角度五、判断

一文详解SpringBoot中控制器的动态注册与卸载

《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp... 目录项目结构1. 创建 Spring Boot 启动类2. 创建一个测试控制器3. 创建动态控制器注

从原理到实战深入理解Java 断言assert

《从原理到实战深入理解Java断言assert》本文深入解析Java断言机制,涵盖语法、工作原理、启用方式及与异常的区别,推荐用于开发阶段的条件检查与状态验证,并强调生产环境应使用参数验证工具类替代... 目录深入理解 Java 断言(assert):从原理到实战引言:为什么需要断言?一、断言基础1.1 语

一文详解Git中分支本地和远程删除的方法

《一文详解Git中分支本地和远程删除的方法》在使用Git进行版本控制的过程中,我们会创建多个分支来进行不同功能的开发,这就容易涉及到如何正确地删除本地分支和远程分支,下面我们就来看看相关的实现方法吧... 目录技术背景实现步骤删除本地分支删除远程www.chinasem.cn分支同步删除信息到其他机器示例步骤

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景

深度解析Spring AOP @Aspect 原理、实战与最佳实践教程

《深度解析SpringAOP@Aspect原理、实战与最佳实践教程》文章系统讲解了SpringAOP核心概念、实现方式及原理,涵盖横切关注点分离、代理机制(JDK/CGLIB)、切入点类型、性能... 目录1. @ASPect 核心概念1.1 AOP 编程范式1.2 @Aspect 关键特性2. 完整代码实

一文详解Java Stream的sorted自定义排序

《一文详解JavaStream的sorted自定义排序》Javastream中的sorted方法是用于对流中的元素进行排序的方法,它可以接受一个comparator参数,用于指定排序规则,sorte... 目录一、sorted 操作的基础原理二、自定义排序的实现方式1. Comparator 接口的 Lam

Java Stream的distinct去重原理分析

《JavaStream的distinct去重原理分析》Javastream中的distinct方法用于去除流中的重复元素,它返回一个包含过滤后唯一元素的新流,该方法会根据元素的hashcode和eq... 目录一、distinct 的基础用法与核心特性二、distinct 的底层实现原理1. 顺序流中的去重

Qt如何实现文本编辑器光标高亮技术

《Qt如何实现文本编辑器光标高亮技术》这篇文章主要为大家详细介绍了Qt如何实现文本编辑器光标高亮技术,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以了解下... 目录实现代码函数作用概述代码详解 + 注释使用 QTextEdit 的高亮技术(重点)总结用到的关键技术点应用场景举例示例优化建议

Spring @Scheduled注解及工作原理

《Spring@Scheduled注解及工作原理》Spring的@Scheduled注解用于标记定时任务,无需额外库,需配置@EnableScheduling,设置fixedRate、fixedDe... 目录1.@Scheduled注解定义2.配置 @Scheduled2.1 开启定时任务支持2.2 创建