问题

游戏中有哪些看上去很简单,但实际上需要极高技术力或是极高成本的细节?

回答
在游戏世界里,确实存在着许多看似平平无奇,实则背后蕴含着惊人技术力或巨大成本的细节。这些细节往往是玩家在沉浸式体验中感知到的“真实感”、“临场感”或“趣味性”的基石。下面我将详细列举一些这类细节,并尽量深入地讲述它们是如何实现和为何如此困难的:

一、 精妙的物理模拟与交互

1. 物体材质与碰撞的真实反馈

表面现象: 当玩家用剑砍击石头,石头会碎裂,并飞溅出石屑;皮革甲会发出“啪嗒”声,金属甲会发出“哐当”声;水面会荡漾,雨滴会击打地面产生涟漪。
技术挑战:
碰撞检测与响应: 不仅要准确判断物体间的碰撞,更要模拟出不同材质的碰撞力学。例如,玻璃破碎时会有特定的碎裂模式和声音,金属碰撞时会有回弹和金属摩擦声。这需要复杂的物理引擎支持,包括刚体动力学、柔体模拟、甚至是基于碎片的模拟(Destruction Physics)。
材质纹理的交互性: 不同的材质需要有不同的视觉反馈。例如,泥土会被踩踏出痕迹,雨水会浸湿衣物并改变其颜色和质感,火焰会熔化金属。这涉及到复杂的着色器(Shaders)编程,需要模拟光线与材质的交互,以及材质属性随时间或交互的变化。
声音的同步与丰富度: 每一类材质的碰撞都需要精心设计的音效,并且要与物理碰撞的力度、速度和角度进行精确同步。这需要大量的音效资源、音频引擎以及实时混合和处理技术。
成本: 开发一套高度真实的物理模拟系统需要大量的研发人员(物理工程师、图形程序员、音效设计师)、高性能的CPU资源来支撑计算,以及海量的美术资源来制作不同材质的碰撞反馈效果和音效。

2. 环境动态变化与影响

表面现象: 在开放世界游戏中,树木会随风摇曳,草地会随玩家经过而弯折,雨水会打湿地面并形成水洼,积雪会随着时间推移而融化或被踩踏。
技术挑战:
风力模拟与粒子系统: 要模拟风对物体的影响,需要一个全局的风力模拟系统,以及能够响应风力的动态物体(如树叶、草、布料)。这通常结合了粒子系统来模拟风吹拂的细微效果(如灰尘、落叶)。
地形动态变化: 地形变化更是复杂。例如,草地弯折需要动态网格变形(Dynamic Mesh Deformation),雨水浸湿地面需要复杂的着色器效果和动态贴图更新。积雪的融化和踩踏则需要更高级的模拟,如基于体素(Voxelbased)的模拟,或者复杂的材质混合与渐变技术。
光照与阴影的实时更新: 当环境发生动态变化时(如下雨、白天变黑夜),光照和阴影也需要实时更新,以保证视觉的连贯性。这要求游戏引擎具备强大的实时全局光照(Global Illumination)和阴影渲染能力。
成本: 实现这些动态环境效果需要顶尖的图形程序员来设计和实现各种模拟算法,大量的CPU和GPU资源来处理大量的动态交互计算和渲染,以及美术团队投入大量精力制作各种状态下的环境资源。

二、 逼真的角色动画与表现

1. 表情与情绪的细微传达

表面现象: 角色在对话时,嘴唇会准确地匹配语音发音,眉毛会随着情绪的变化而微妙地抽动,眼神会流露出喜怒哀乐。
技术挑战:
面部表情绑定与驱动: 这需要极其精细的面部骨骼绑定(Facial Rigging),包含大量的骨骼和控制点来模拟面部肌肉的运动。然后,通过动作捕捉(Motion Capture)数据或程序化驱动(Procedural Animation)来控制这些骨骼,实现逼真的表情。
语音与口型同步(Lip Sync): 这是一个非常耗时且技术要求高的工作。需要将语音分析成不同的发音单元(Phonemes),然后将这些单元映射到预设的面部表情动画上,并保证其与语音的节奏和节奏完美同步。这通常需要专门的工具和大量的人工微调。
眼球追踪与注视点模拟: 逼真的眼神交流是情感表达的关键。需要模拟眼球的转动、瞳孔的变化,以及角色在不同场景下的注视点,这些都需要精密的控制和算法。
成本: 顶尖的角色动画师、面部绑定师、动画程序员,以及昂贵的动作捕捉设备和团队,都需要大量的资金投入。即使是程序化的口型同步,也需要大量的开发时间和优化。

2. 多样的肢体动作与反应

表面现象: 角色在奔跑时,会根据地形的高低起伏而调整步态;受到攻击时,会根据攻击的方向和力度产生不同的受击反应;在不同环境下,会有不同的交互动作(如攀爬、游泳)。
技术挑战:
程序化动画生成(Procedural Animation): 为了避免制作数以万计的固定动画来应对各种情况,很多游戏会采用程序化动画技术。例如,程序化行走(IK Inverse Kinematics)可以根据地形自动调整角色的腿部动作,使其保持稳定。
动作融合与过渡: 将不同的动作(如跑动、跳跃、受击、翻滚)平滑地融合在一起,并在不同的动作之间实现自然的过渡,需要复杂的动画状态机(Animation State Machines)和动画融合算法。
物理驱动的动画: 例如,角色在跌倒时,身体的摆动、四肢的伸展等,可以部分由物理引擎来驱动,产生更具随机性和真实感的反应。
全身IK系统: 很多游戏会使用全身IK系统来确保角色在与环境交互时(如抓住梯子、踏上凸起的石头)肢体能够正确地触碰到目标。
成本: 动画程序员需要掌握复杂的算法和游戏引擎的动画系统,动画师需要设计大量的动作基元,并且需要进行大量的测试和调整来确保所有动作能够顺畅地融合和响应。

三、 复杂的游戏AI与决策

1. 智能的敌方AI

表面现象: 敌人会根据玩家的行为做出合理的战术反应,会寻找掩体、协同作战、包抄玩家,甚至会学习玩家的套路。
技术挑战:
行为树(Behavior Trees)与状态机(State Machines): 这是AI的核心设计模式。行为树可以定义一系列复杂的行为逻辑,允许AI在不同情况下做出选择。状态机则定义了AI在不同状态(如巡逻、战斗、搜寻)之间的切换。
路径寻找(Pathfinding): AI需要能够在复杂的地图环境中找到到达目标的最短或最优路径,例如使用A算法。
感知系统(Perception System): AI需要能够感知周围环境,包括听到声音、看到敌人、发现线索等。这涉及到视锥(Field of View)、听觉范围等模拟。
学习与适应: 更高级的AI甚至会具备一定的学习能力,通过分析玩家的战术并调整自身的行为模式,使其更具挑战性。这可能涉及到机器学习技术。
成本: AI程序员是游戏开发中的核心岗位之一。设计和实现一个能够提供良好游戏体验的智能AI,需要大量的逻辑设计、编程工作和反复的测试调整,其复杂性往往不亚于游戏的主体玩法。

2. 逼真的NPC行为

表面现象: 非玩家角色(NPC)不仅仅是站桩的背景,他们有自己的生活规律,会在城市中走动、与其他人互动、执行自己的任务,甚至对玩家的行为做出反应。
技术挑战:
日程表与生活模拟: 为大量的NPC设计一套相对独立的日程表和行为模式,使其在游戏世界中表现得更加生动。
社会化AI: NPC之间可能存在社交关系,会互相交流、合作或争执。
环境互动: NPC会与环境中的物体进行互动,如坐下、交谈、购买商品等。
动态响应: NPC会根据玩家的行为(如打架、偷窃)做出不同的反应,如逃跑、报警、帮助玩家等。
成本: 设计和实现大量有意义的NPC行为需要大量的脚本编写、动画制作和逻辑开发。当这些NPC的数量庞大时,其工作量和技术挑战都会指数级增长。

四、 高度精细的画面表现

1. 光照与阴影的真实感

表面现象: 阳光穿过树叶的缝隙洒下斑驳的光影,物体在不同光源下的阴影边缘清晰而柔和,黑暗的环境中有微弱的光线反射。
技术挑战:
实时全局光照(Realtime Global Illumination): 传统的阴影计算只考虑直射光,而全局光照则模拟了光线在场景中多次反射后对物体颜色的影响,这能极大地提升画面的真实感。实现实时全局光照的技术非常复杂,例如延迟渲染(Deferred Rendering)结合光照探针(Light Probes)或屏幕空间反射(Screen Space Reflections)。
体积光(Volumetric Lighting)与雾效: 模拟光线在空气中的散射效果,如穿过窗口的光束,能显著增强画面的氛围感。
精确的阴影投射与接收: 确保所有物体都能正确地投射和接收阴影,并且阴影的柔和度、形状能够随着光源和物体距离的变化而自然调整。
成本: 顶级的图形程序员、美术师需要掌握复杂的渲染管线(Render Pipeline)和 shader 编程。高昂的GPU算力是支撑这些效果的必要条件。

2. 材质的细节表现

表面现象: 金属表面的反光逼真,水面有真实的折射和反射效果,皮肤有细腻的毛孔和纹理,布料有自然的褶皱和光泽。
技术挑战:
PBR(Physically Based Rendering)渲染: 这是一种基于物理学的渲染方法,通过模拟光线与物体表面交互的物理规律,来生成更加逼真的材质表现。实现PBR需要对材质的反射率、粗糙度、金属度等属性有精确的定义和模拟。
法线贴图(Normal Mapping)、高度贴图(Height Mapping)、置换贴图(Displacement Mapping): 这些技术用于模拟物体表面的微观细节,如凹凸、划痕等。置换贴图甚至可以改变网格的几何形状,产生更真实的立体感。
次表面散射(Subsurface Scattering): 对于像皮肤、蜡烛等半透明材质,光线会穿透表面并被内部散射,产生柔和的光晕效果。模拟次表面散射非常复杂。
焦散(Caustics): 光线通过折射或反射后,在表面形成的明暗交错的光斑效果,如水底的波光粼粼。
成本: 美术团队需要投入大量精力制作高精度的材质贴图。渲染程序员需要实现各种复杂的着色器算法。

五、 细致入微的音效与音乐

1. 空间音频与声场模拟

表面现象: 玩家能清楚地听到脚步声是从左前方传来的,远处传来的枪声定位准确,在不同的房间里,声音的回声和衰减也不同。
技术挑战:
HRTF(HeadRelated Transfer Function)与3D音频: 模拟声音在头部和耳朵处的传播,以提供逼真的空间感知,让玩家分辨声音的方位和距离。
混响(Reverb)与回声(Echo)模拟: 根据环境的材质和大小,实时模拟声音的反射和衰减,创造出不同空间感(如开阔的场地、狭窄的通道)。
声源的动态遮挡: 当物体挡住声源时,声音的传播方式会发生变化,需要精确模拟。
成本: 音频工程师需要使用专业的音频引擎和工具,并进行大量的音频设计和参数调整。

2. 动态音乐系统

表面现象: 游戏音乐会随着玩家的行为和场景的变化而自然切换和编排,在紧张时变得激昂,在平静时变得舒缓。
技术挑战:
音乐分层与组合: 将音乐分解成不同的乐器、节奏、旋律等层级,根据游戏状态动态地进行组合和叠加,以创造出无缝的音乐过渡。
触发器与情绪分析: 根据游戏事件(如战斗开始、发现敌人、解开谜题)来触发音乐的变化,并根据玩家的情绪状态来调整音乐的表现力。
音乐状态机: 设计复杂的音乐状态机,来管理不同音乐片段之间的过渡和交叉。
成本: 需要专业的音乐制作人、编曲家和音频程序员协同合作,设计一套复杂的音乐生成和控制系统。

总结

这些看似简单的细节,背后都凝聚了开发团队巨大的心血。它们可能是:

无数次的迭代和优化: 为了让一个动作、一个效果达到最佳的体验,往往需要经过成百上千次的测试和调整。
庞大而专业的团队: 从程序员、美术师、动画师、音效师到策划师,每个环节的专业人员都需要精通自己的领域。
先进的技术与工具: 游戏引擎本身、专门的开发工具、动作捕捉设备等都是高成本的体现。
巨额的开发周期和资金投入: 一个AAA级游戏的开发周期可能长达数年,投入数亿人民币是常有的事。

正是这些被隐藏起来的细节,构成了我们所体验到的游戏世界的“灵魂”,让游戏不再是冰冷的像素和代码,而是充满生命力和感染力的艺术品。玩家在享受游戏乐趣的同时,也在不经意间体验着这些技术的结晶和成本的堆砌。

网友意见

user avatar

游戏里有一个即使是小学生也会做,但博士生都未必做的好的问题.

它是如此常见,几乎出现在除了<<nekopara>>外的所有的FPS游戏和绝大部分的RTS中.

如果你打游戏发现你的CPU烫的可以煎牛排,那么当中恐怕有一半的热量和这玩意多多少少有所关联.

它导致了海量的bug,包括但不限于五毛特效级别的穿模,人物或别的物体奇怪的舞蹈及鬼畜,血条消失术及瞬间移动和突然上天,都是因为它难以处理或处理不好.

但它听起来看上去真的超简单,我甚至不用堆些专业术语大家都看得懂,但在你没有真正把这玩意做出来之前,你对这玩意所述的一切算法和理论的不屑,都是在"云".

说了那么多,那么这玩意到底是啥,其实真也不是啥高大上的东西,这玩意叫碰撞检测.简单来说,就是判断游戏里两个物体有没有碰撞.我们先来举个最简单的栗子

ObjectA和ObjectB是游戏世界中的两个圆,如何判断它们有没有碰撞,你可能开始骂我撒币了,因为只要长了眼睛就能看出来这两个圆没碰在一起,但可惜我们不能靠眼睛这么玩,计算机有计算机的玩法,当然,这仍然很简单

设Object A的圆心坐标为(x1,y1)半径为r1,设Object B的圆心坐标为(x2,y2)半径为r2,然后我们计算圆心之间的距离d和r1+r2,如果d<=r1+r2,那么这两个圆毫无疑问是碰撞在一起的,如果d>r1+r2,那么这两个圆就没碰在一起,如果你是码农你可能会用 和 来比较,这样就可能不用计算一次可能更耗时的开平方,不过没关系,这无关痛痒,这仍然超简单的是不.没关系,显然大部分游戏中只有2个Object的情况毕竟是少数,显然我们需要考虑2个以上Object的情况,比如说3个

那么,如何判断这三个Object相互之间有没有碰撞关系呢,其实这也不是事儿,比如说上面三个Object,我们只需要依据两两碰撞的办法,分别判断A和B,A和C,B和C之间有没有碰撞在一起就行了,我相信很大一部分初学了C语言,想做一个弹幕游戏大部分就使用了上面这个办法,但如果我们把Object数量加到4个,问题就来了,我们发现2个Object的时候,我们只需要计算一次碰撞判断,有3个Object的时候,这个计算增加到了3次,如果这个Object增加到了4个,那我们就需要计算A-B,A-C,A-D,B-C,B-D,C-D一共是6次碰撞检测计算,当然,6次对于计算机来说这并不算什么,依据这种算法碰撞次数如果游戏中有n个Object,我们就需要计算 次碰撞,比如101个Object我们需要计算100+99+98+97+....1共计5050次碰撞,当然对CPU来说这仍然不算什么.但如果这个游戏是一个多人大型战场类游戏,你发现阵地上有1000发炮弹在到处飞时,你就可以闻到CPU的香气了.

当然,要解决上面这个问题依然不是什么很难的事情,比如下面这种情况,一个游戏场景中有4个Object

我们把整个游戏世界均等分为4份

显然,我们可以先给游戏世界里的Object分个类,首先A和B在第一个区域,C和D在第4个区域,显然的,不同区域之间的Object显然是不会碰撞在一起的,于是,我们只需要2次碰撞计算就可以得出碰撞结果了,这个算法又叫四叉树碰撞检测算法,按树结构的理解是,我们建立了一个有四个子节点的树结构,然后把游戏里的对象划分进去,没关系,反正其算法的原理大致就是一个分治的思想,不管怎么说,这确实很好的优化了碰撞检测的时间复杂度

到这一步,你呵呵一乐,就这?也没见多复杂啊,放心,相当一部分码农的理论也就到了这一步,所以成就了很多的"云码农",坐好,现在我们开始加速了.

某天你和你的基(姬)友相约上线吃鸡,图上每一个圆点代表着一个人,显然区域4肥的流油导致很多玩家纷纷下饺子,那么这个时候,四叉树分割的算法显然就不能发挥其最大的优势了,毕竟大部分的节点都分布在了区域4中

你说,这好办啊,兵来将挡水来土掩,我们对区域4再进行一次四叉树分割不就好了

你看,问题很好的解决了,这不也没啥大不了的不是,你甚至表示如果区域4里的object再多一点,你可以再分一次

当你说到这句话的时候,你恐怕现在心里也有点发虚了,因为你注意到上面的分割算法中,有些Object是横跨了多个区域的

就比如上图中两个用蓝色框框框出来的那两个Object,它们横跨了两个区域,这也就意味着,你必须对这两个Object进行分片.也就是说,四叉树的多个叶子需要同时存储这个Object的节点,实际上四叉树算法看上去很美,实际上对Object的分类实际上也是做了一次碰撞检测,当然横跨2个区域的情况并不是那么极端,假如现在一个玩家他变身成了奥特曼,变成了一个无比庞大的Object(如下图的蓝色区域)

你发现,这个时候四叉树的优化对这个节点毫无作用,你还需要承担这个节点分割带来的额外性能开销,出现了一个负优化的结果,那么这个时候你该怎么办呢?这个时候恐怕有人会说,把这个那么大的object存储在四叉树的父节点不就行了,我们不分片,只要这个Object占据了所有子节点的区域,,那么就将它存储在父节点中.

当然,如果只是"云代码"的话,上面的处理是成立的,但是实际要做的话,上面的处理是沙雕的,没法搞的,纸上谈兵的,因为在四叉树的分类中,节点是一个一个添加进去的,你无法控制这个四叉树什么时候会进行进一步的划分,比如上面这个蓝色Object现在它当然占据了整个地图的所有节点,但是当最右下角的区域出现越来越多新的Object不得不进行进一步分片时,你就会发现这个蓝色的Object在父节点中待不下去了

好了,一旦出现这个情况,这个大型Object不再能待在覆盖所有子节点中的父节点了,你将不得不再对这个大型的Object进行一次额外开销的分片计算,然后再将它重新分发到各个子节点中,如果这种非常大的Object还很多的话,你发现你还不如一开始就将它进行分片呢.但这个办法并非不可取,如果你知道你游戏里这种比较大的Object并不多,这种父节点存储法也许真能对碰撞的复杂度进行优化,所以这仍然是我们说的,不同情况不同考虑,真以为四叉树就长这个样能解决所有的碰撞处理算法,抱歉,不存在的.

好了,到这里现在开始,碰撞检测我就要只提问题不说解决办法了,为啥,因为难啊,不同情况需要依据游戏的情况进行不同情况的优化,我只是向你展示的是,碰撞检测并不像看上去那么简单.它仍然存在一堆问题需要你去解决

那么我们再举个栗子

问,上图中现在ObjectA是一个子弹,ObjectB是一个怪兽,ObjectA和ObjectB发生了碰撞,碰撞了几次?

你可能很疑惑为什么我问了这样一个问题,但它确实是四叉树分片带来的又一个问题,如果A,B进行了分片,那么首先在分片过程中,A和B因为分片同时存在了四叉树分割的两个区域中,这意味着在四叉树的最终计算结果中,它将在两个不同的区域都发生了碰撞,碰撞了两次,如果不将重复的碰撞结果进行剔除,那么,这个怪兽将会承受这个子弹带来的双倍伤害,当然怪兽这样都得偷着乐了,要是子弹和它刚好在四叉树的中间区域也就是横跨了四个区域,那么它将承受因为四叉树优化带来的四倍伤害.那么,你会如何剔除重复碰撞呢,当然,你得好好想想这个问题,不然你的四叉树优化,可能又是个负优化.

截至目前,你看虽然我们讨论的是碰撞检测,仅仅一个四叉树就带来了那么多乱七八糟的问题了,没关系,我们现在讨论的还是算法方面的,如果你实际操刀写代码的话,你有没有想过四叉树是一个动态的结构,我们如何给四叉树的节点分配内存呢,

malloc?new?

用了你就沙币了,如果一个游戏里有100个object,那么创建四叉树结构至少需要100次分配节点,这也就意味着你很可能需要向系统申请100次节点的内存然后再用100次delete或者free释放掉,真的,你还不如不用四叉树呢,内存的分配与释放,可能比你直接计算碰撞还要慢,而且还能带来一堆内存碎片和缓存命中带来的一堆问题

于是你不得不重新接管内存的管理方式比如使用一个内存池来对这个四叉树结构进行管理,得,我们成功将碰撞检测这一个算法上的问题上升到了内存管理上的另一个问题,而且这两个问题你都得好好解决..因为不同类型的游戏,类似上面四叉树的空间划分算法还有很多,同时也带来了更多海量的问题,

你会发现你很难找到一个万金油类型的碰撞检测算法,依据这个游戏的不同,你得分类考虑,然后在性能与游戏体验上找到一个平衡点,当然目前很多的游戏引擎并不需要你考虑这些碰撞算法,显然的,如果使用通用的算法,你就得在性能与空间上付出点代价.

到这里你可能吐了一口气,原来还真是有些麻烦啊,抱歉,上面的东西考虑的只能说是凑活能用,其实只是冰山一角

因为游戏世界里的Object,不是长的都是规规矩矩的一个圆

有这样的

还有这样的

当然,不规则几何的碰撞检测还只是"碰撞检测",还没上升到"碰撞"问题的处理上来,比如隧穿效应和PUBG里的名场面粘滞效应

现在我们再来聊聊游戏世界是如何运行的,游戏世界的时间和我们现实世界的时间有所不一样,例如一辆汽车在高速公路上飞驰一秒钟,那么你可以得出它在0.12345秒时,这辆车的位置与状态,但如果这辆车跑在游戏世界中,这恐怕就办不到了

在游戏世界中,时间是离散的,一个称作游戏循环的逻辑结构控制着游戏世界的运行,一个称作时间粒度的变量是游戏世界时间运行的最小单位,在大多数情况下这个单位不会被进一步的细分.

在每个游戏循环中,会对游戏世界中的每一个对象进行一次更新(当然有时会对视口外或一些静态对象优化),举个栗子,如果游戏世界的时间粒度是10ms,那么,游戏世界将会计算10ms,20ms,30ms....时游戏世界中对象的状态

正因为这种运行方式,你会发现游戏世界的模拟并不能直接使用一些连续的函数来描述,例如游戏中弹道的计算或者抛物线方程,在游戏世界中未必好使,这类方程在现实中计算十分方便,毕竟我们可以直接用微积分等手段来计算出具体时间时的位置,速度,但在游戏中引用这类方程大多控制不便不利于优化设计复杂,这涉及一个将连续函数离散化的问题,因此,在一个游戏循环中,比如10ms-20ms这段时间里,在游戏世界中我们大多将这段时间的受力或者速度当做一个恒定的值因此你会发现,如果你要控制一个物体做抛物线运动,其最终的落点和你使用抛物线方程的落点最终会有所不一样,可以这么说,尽管PUBG游戏如何宣称这是一款真实的物理引擎,其最终都只是一个广告词,它与真实世界的模拟仍然有诸多的差别.

这类离散的差别也导致了一些很有意思的bug,其中一个便是遂穿效应,例如在上面的图中,10ms和20ms中出现了一堵墙

那么,这个碰撞根本不会发生,就好像汽车穿过了这堵墙一样,如果要避免这种情况,要么把墙体的宽度变宽点,要么就减少时间粒度比如控制在5ms

但正如你所知道的一样,因为每次循环都需要对游戏中所有需要更新的物体进行一次计算,因此,减少时间粒度所耗费的性能损耗往往是非常明显的,在大多数情况下,游戏设计人员会刻意减少游戏里物体的速度或者说使用第一种办法把物体做的厚一点

另一个很有意思的bug是粘滞,这也是碰撞检测方面的bug,在众多即使是3A大作的游戏中,这个bug也非常的常见并且优化困难,避免需要耗费巨大的代价,我们同样举个栗子

在上图中,一辆车装上了一个球,因为时间粒度关系,当碰撞发生时,车已经嵌入到球当中了,这个时候碰撞已经发生,按照"真实的物理引擎"计算,车应该受到一个立即的反作用力,并速度方向应该立即变为反方向

但是,因为碰撞存在能量损失,因此,回退的速度会比撞击时的瞬时速度更慢,导致了在下一次游戏循环时,车仍然没有脱离球的范围,这导致了物理引擎认为,车第二次撞上了球(实际碰撞只发生了一次),于是车又改变了速度方向,再次撞入了球,因为速度再次衰减,所以车就和这个球粘上了,如果两者状态不改变将并永远不会脱离

这就导致了两个物体黏在一块,两边反复抖动,最终导致了神奇的鬼畜现象,如果碰撞是有伤害的,那么就会导致粘滞发生后不久就会瞬间爆炸

写了那么多,但其实碰撞检测有关的东西远不止上面说的那么点,游戏引擎开发的事儿,说多了都是泪,很多东西看上去很简单.但经验告诉我常常是理想很丰满现实很骨感.在做出来之前一切的感觉只是感觉

毕竟: 少说废话,放码过来

放个广告,欢迎游戏开发大佬入驻

user avatar


@DBinary 大佬回答了关于游戏世界中碰撞问题所引发的各种 bug,我在几天前编了台球的程序,全部遇到了……

基本思路

我并没有按照拉普拉斯妖( )的方式编写程序:给定台球桌上所有球的位置、动量,然后一次性预言接下来一切的运动,直至所有球速度为零(由于摩擦力),然后继续下一杆球的撞击…… 我没有这么大的野心。 我采取的思路非常简单粗暴,设置“普朗克时间”、“普朗克长度”,然后使用非常局部性的判断:如果两颗运动的球(至少有一者速度不为零),相距小于所谓的“普朗克长度”,那么我们就判断为两者发生碰撞。依据人视觉的暂留效应,使用 、、 等初级绘图函数快速绘图的方式,实现动画效果,其中的时间间隔为 左右,此即为“普朗克时间”。

优缺点

优点是算法上容易实现,效果还可以,相对来说比较丝滑。只是 说实话运行速度一直为人诟病,所以遇到“多球运动”还是免不了慢下来。另外,由于“普朗克时间”内的运动的不确定性——在这个短暂的时间间隔内,复杂的运动是无法判断的,并且可能会发生碰撞时间先后颠倒的错误,但是我们都不得而知。感觉这个很类似于量子力学中的“测不准原理”。 不过,即便按照拉普拉斯的哲学理念去编写程序,由于计算机自身天然的离散性(或者干脆说量子性),截断误差依然会影响桌面小球的运动,并且随着运动的复杂性增加,误差是不可避免的。 所以,更完美的思路,既不是鼠目寸光,也不是高瞻远瞩,而是取其中道。不过,我本来就是一个玩家的心态,就不挑战这一艰难的任务了。 这个程序还是有一点点 ,这个在诸位玩耍的时候慢慢体会吧(邪魅一笑~)

注:其实这个 就是 @DBinary 文中所写“鬼畜碰撞”,我称之为“量子纠缠”。

感想

我和以前云大师弟 @littleNewton 探讨了这个问题,大佬的一句话高度概括了此类游戏的: 台球游戏简直是计算机格论发展史的缩影。 (原话大概如此,我先记录下来,后面确认一下) 师弟顺便和我介绍了计算机领域的圣杯级别的问题 、 、 ……原来这不仅是我的困惑,也是计算机几代人的困惑。作为外行人的我感到受益匪浅。后来我们由聊了聊很多学习方面的困惑,学科之间的分野、数学证明的执着等等。 谈话中间,我半开玩笑地说: “说不定我们这个世界也是一段使用相同算法的程序呢。”



哦对了,原贴里有代码——

user avatar

我说一个简单的:角色怎么样自然地走路

Motion Matching这个技术发展成熟之前,我们大部分的游戏中角色动作都是由状态机决定的,什么叫状态机呢?状态机就是我们预先定义了一些节点作为状态,比如跑,跳,下蹲,发呆。当我们传进用户输入的时候(比如按下了跑的按钮),那么角色将从一个状态转移到另一个状态,这个输入称为状态转移函数,也就是我们预定的一些规则,比如当角色在发呆的时候,按下跑的按钮,角色就转换为奔跑的状态。这张图是一个简单的角色移动的动画状态机:

看起来似乎还不错也挺简单的对吧?那么问题在哪里呢?

第一,当角色动画从一个状态转移到另一个状态的时候,怎么样产生一个平滑自然的动作过度?传统的状态机方法,往往是在当前状态到目标动作间,创建一个简单粗暴的线性插值,又或者直接停止当前动画的片段播放,转而播放目标动作的动画片段。这两种方法都会产生一个问题:角色动作非常生硬。比如角色上一秒正在向前奔跑,玩家突然按下了后退键,这时候角色应该如何行动?真实世界中的人可能会先伸出一只脚刹停,然后转身,再反向发力奔跑。但是如果使用动画状态机,往往角色的动作并没有这个过度,而是一瞬间从向前跑变成了向后跑的姿势,这就是角色动作中不自然的地方,玩家或许说不上来为什么,但是他们感觉得到。

第二,当角色的动画状态增加的时候怎么办?根据我们前面的描述,状态转移函数其实是人为指定的规则,当状态增加时,也就意味这新的规则需要被传入,比如我们自然而然的知道,人跳在空中的时候,是不能转移到奔跑状态的,而是要先落地,但是这些规则计算机并不知道,所以需要人为指定,假设一个游戏中,角色除了发呆,奔跑,跳跃,还有爬墙,甩绳子,开枪,拳击这些状态(通常的第一人称类游戏,往往都有不下几十个状态),那么理论上设计者需要考虑任意两个状态之间有无转换,如何转换,那么其设计的复杂度会迅速提升,于是动画师就需要浪费大量的时间用于制定这些运动规则。

育碧最早开始了motion matching的尝试,所谓motion matching,其核心思想是,不再人为指定角色动作之间的转换,而是单纯地指定目标动作,而从当前动作到目标动作之间的插帧,则由计算机从动作数据库中自动找出一个最佳匹配,或者根据已有的动作数据,基于插值生成一个新的,最合理的动作。那么如何衡量一个动作的合理性呢?这里我们可以引入非常多的“约束”,这个“约束”可能是基于用户的输入(比如按向后跑的键,强制要求角色掉头);可能是角色当前的速度、加速度;可能是角色的IK(反向动力学)数据(比如一个角色正在上楼,下一个动作脚尖必须贴在楼梯地面上);可能是物理引擎的碰撞检测反馈(比如下一秒角色碰到了一个比较矮的栏杆,必须低头才能通过)。

如果我们把角色身上所有骨骼最终的位置、朝向看作一系列的变量,上面提到的约束看作是这些变量组成的等式或不等式,将基于动捕录制好的所有动作张成的线性空间看作这个约束的解空间,那么这个问题就变成了对于有限个变量和约束条件,在解空间内搜索最佳解的问题。于是动画师们基于经验去指定规则的方案,就变成了一个纯粹的数学物理问题。

我们来看看基于motion matching这一思想实现的角色动作:

即使是怎么走路这么简单的问题,为了解决好也仍然需要大量的努力。所以真正了不起的技术往往都藏在这些不起眼的细节中。

=================================================

补充一篇今年Siggraph 2020的新paper[1],仍然由育碧带来。这次育碧尝试了把神经网络和传统Motion Matching方案结合起来,在Motion Matching的基础框架下,把其中某些步骤的计算(需要消耗大量内存和计算量的)通过trained NN kernel来替换。这样既保证了学习的启发性(大量减少训练时长,同时保证结果的可预测性),又能够加速运行时的速度,减少存储开销。

具体视频效果看这里:

参考

  1. ^LEARNED MOTION MATCHING https://montreal.ubisoft.com/en/learned-motion-matching-2/

类似的话题

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有