关于我们如何达成这项共同的公约已有很长的历史,在此过程中还面临着许多令人着迷的挑战,因此,我将分阶段尝试激发它:
1.问题:设备以不同的速度运行
您是否曾经尝试过在现代PC上玩旧的DOS游戏,但它运行起来却速度很快,只是模糊而已?
许多旧游戏的更新循环非常幼稚-他们收集输入,更新游戏状态并以硬件允许的速度进行渲染,而无需考虑已花费了多少时间。这意味着一旦硬件发生变化,游戏玩法就会发生变化。
我们通常希望玩家使用的是去年的手机或最新型号,高端游戏台式机或台式机,只要在一系列设备上(只要符合最低要求),就可以获得一致的体验和游戏体验。中端笔记本电脑。
特别是对于具有竞争力的游戏(无论是多人游戏还是通过排行榜),我们都不希望在特定设备上运行的玩家比其他玩家具有优势,因为它们可以运行得更快或有更多的时间做出反应。
这里的surefire解决方案是锁定我们进行游戏状态更新的速率。这样我们可以保证结果将始终相同。
2.那么,为什么不只是锁定帧速率(例如使用VSync),而仍以锁步的方式运行游戏状态更新和渲染?
这可以奏效,但并不总是对听众可口。长时间以30 fps的速度稳定运行被认为是游戏的黄金标准。现在,玩家通常期望60 fps作为最低限制,尤其是在多人动作游戏中,随着我们对期望值的改变,一些较早的游戏现在看起来也很不稳定。特别是还有一群PC播放器的声音播放器,他们完全反对对锁进行帧速率处理。他们为尖端的硬件付出了高昂的代价,并希望能够使用该计算能力来实现其能够提供的最平滑,最高保真度的渲染。
特别是在VR中,帧速率为王,标准不断提高。在最近VR兴起的早期,游戏通常以60 fps的速度运行。现在更标准的是90,而像PSVR这样的硬件开始支持120。这可能还会继续增加。因此,如果VR游戏将其帧速率限制在今天可以接受和接受的水平,则随着硬件和期望的进一步发展,它有可能被抛在后面。
(通常,当被告知“玩家无法以比XXX更快的速度感知任何东西”时请多加注意,因为它通常基于特定类型的“感知”,例如按顺序识别帧。感知运动连续性通常要远得多)敏感。)
这里的最后一个问题是,使用锁定帧率的游戏也需要保持保守-如果您在游戏中碰巧要更新和显示异常多的物体的那一刻,就不想错过帧了截止日期,并导致明显的结结或结结。因此,您要么需要将内容预算设置得足够低以留有余量,要么需要投资更复杂的动态质量调整功能,以避免将整个播放体验与最小规格硬件上最差的性能挂钩。
如果性能问题出现在开发的后期,当所有现有系统的构建和调试都假设采用了一个锁步渲染帧速率(现在您无法总是做到)时,这可能会特别成问题。解耦更新和渲染速率为处理性能变化提供了更大的灵活性。
3.在固定的时间步上更新是否不具有与(2)相同的问题?
我认为这是原始问题的实质:如果我们将更新解耦,有时渲染两个帧之间没有游戏状态更新,那么这与以较低帧速率进行锁步渲染不一样,因为它没有可见的变化屏幕?
实际上,游戏使用几种不同的方式将这些更新解耦以达到良好效果:
a)更新速率可以比渲染的帧速率更快
正如tyjkenn在另一个答案中指出的那样,尤其是物理学,通常以比渲染更高的频率步进,这有助于最小化积分误差并给出更准确的碰撞。因此,您可能需要5或10或50,而不是在渲染的帧之间进行0或1更新。
现在,以120 fps渲染的玩家每帧可以获得2次更新,而使用低规格硬件以30 fps渲染的玩家则每帧获得8次更新,并且它们的游戏均以相同的每秒钟实时游戏速度运行。更好的硬件使其看上去更流畅,但不会从根本上改变游戏的工作方式。
如果更新速率与帧速率不匹配,就有可能在两者之间获得“拍频”。例如。在大多数帧中,我们有足够的时间来更新4个游戏状态并有少量剩余,因此每隔一段时间,我们就有足够的存储空间来在一个帧中进行5个更新,从而在运动中产生一些跳跃或停顿。这可以通过...解决
b)在更新之间内插(或外推)游戏状态
在这里,我们经常让游戏状态在未来保持一个固定的时间步长,并存储来自两个最新状态的足够信息,以便我们可以在它们之间绘制任意点。然后,当我们准备在屏幕上显示一个新的帧时,我们会融合到适当的时刻,仅用于显示目的(即,我们在这里不修改基本的游戏状态)
只要做得正确,只要我们不会跌落得太低,它就可以使运动感觉像黄油一样平滑,甚至有助于掩盖帧率的某些波动。
c)增加非游戏状态变化的流畅度
即使不插值游戏状态,我们仍然可以获得一定程度的流畅性。
纯粹的视觉变化(例如角色动画,粒子系统或VFX)以及用户界面元素(例如HUD)通常独立于游戏状态的固定时间步进行更新。这意味着,如果我们每帧多次对游戏状态进行滴答,我们就不必为每次滴答付出代价,而只是在最终渲染阶段才付出。取而代之的是,我们缩放这些效果的播放速度以匹配帧的长度,从而使它们在渲染帧速率允许的情况下流畅播放,而不会影响游戏速度或公平性,如(1)所述。
摄像机移动也可以做到这一点- 特别是在VR中,有时我们会多次显示同一帧,但是要重新投影以考虑到玩家之间的头部移动,即使我们可以改善延迟和舒适度不会以如此快的速度自然渲染所有内容。一些游戏流媒体系统(游戏在服务器上运行,而播放器仅运行瘦客户端)也使用了该版本。
4.为什么不对所有内容都使用(c)样式?如果它适用于动画和UI,我们是否不能简单地缩放游戏状态更新以匹配当前帧速率?
是*这是可能的,但是不简单。
这个答案已经有点长了,所以我将不做所有详细的细节,只是一个简短的摘要:
通过乘以deltaTime
作品来适应可变长度更新以进行 线性更改(例如,以恒定速度移动,计时器的倒数或沿动画时间轴的进度)
不幸的是,游戏的许多方面都是非线性的。即使是像重力这样简单的事情,也需要更复杂的集成技术或更高分辨率的子步骤,以避免在变化的帧频下产生不同的结果。播放器的输入和控制本身就是非线性的巨大来源。
特别是,离散冲突检测和解决方案的结果取决于更新速率,如果帧太长,则会导致隧穿和抖动错误。因此,可变的帧速率迫使我们对更多内容使用更复杂/更昂贵的连续碰撞检测方法,或者容忍我们物理学中的可变性。当物体沿弧线移动时,即使是连续的碰撞检测也面临挑战,需要更短的时间步...
因此,在一般情况下,对于中等复杂度的游戏,完全通过deltaTime
缩放来保持一致的行为和公平性是介于非常困难和维护密集到完全不可行之间的。
标准化更新速率使我们可以保证在一定范围内(通常使用更简单的代码)在更多情况下的行为一致。
保持更新速度与渲染脱钩,可以让我们灵活地控制体验的流畅性和性能,而无需更改游戏逻辑。
即使那样,我们也永远无法获得真正的“完美”帧速率独立性,但是就像游戏中的许多方法一样,它为我们提供了一种可控制的方法,可以根据给定游戏的需求向“足够好”拨号。因此,通常将其作为有用的起点。