修复抖动、卡顿和输入延迟

什么是抖动、卡顿和输入延迟?

抖动(Jitter)和卡顿(stutter)是即使游戏在全速运行时,也可能出现在屏幕上物体可见运动中的两种不同变化,可能会影响游戏体验。这些问题在世界以恒定速度朝着固定方向运动的游戏中影响最明显, 比如跑酷或平台类游戏.

输入延迟与抖动和卡顿无关,但也是经常为人讨论的话题。输入延迟指在鼠标、键盘、控制器与触屏在与游戏进行互动时,在屏幕上所呈现的视觉延迟,产生的原因与游戏代码、引擎代码及外部因素(如硬件因素)等方面有关。尤其是在第一人称游戏当中,输入延迟尤为明显。输入延迟无法消除,但可以通过某些手段来减少输入延迟。

抖动和卡顿的区分

一款在正常帧下运行, 而不显示任何效果的游戏将显得平滑:

../../_images/motion_normal.gif

游戏展示了抖动将以非常细微的方式持续抖动:

../../_images/motion_jitter.gif

最后,存在“卡顿”的游戏看上去是流畅的,但似乎每隔几秒钟就会停顿回滚一帧

../../_images/motion_stutter.gif

抖动

产生抖动的原因有很多,最典型的情况发生在运行游戏时的物理频率(通常为 60 Hz)以与显示器刷新率不同。检查你的显示器刷新率是否为 60 Hz。

这通常不是一个问题, 因为大多数显示器都是60赫兹, 而且从Godot 3.1开始, 引入了一个帧定时器, 尽量与刷新同步.

有时只有某些对象会出现抖动(角色或背景)。当它们在不同的时间源中处理时(一个在物理步骤中处理,而另一个在空闲步骤中处理),就会发生这种情况。Godot 3.1 对此进行了一些改进,从允许在常规 _process() 循环中对运动体进行动画处理,到在帧计时器中进行进一步修复。

卡顿

产生卡顿有两个不同原因。第一个,也是最明显的一个,就是游戏无法保持完整的帧率性能。解决方法是因游戏而异的,需要进行优化。

第二个原因更复杂,因为它通常与引擎或游戏无关,而与底层操作系统有关。下面是不同操作系统上,关于卡顿的一些信息。

在支持禁用 V-Sync 的平台上,通过在项目设置中禁用 V-Sync 可以减少卡顿现象。但这会导致出现撕裂现象,尤其是在刷新率较低的显示器上。如果你的显示器支持,请考虑启用可变刷新率(G-Sync/FreeSync)并保持 V-Sync 启用。这可以避免在不引入撕裂现象的情况下,缓解某些形式的卡顿现象。

强制显卡使用最大性能配置文件也有助于减少卡顿,但代价是增加 GPU 功耗。

Windows

众所周知,Windows 操作系统在窗口化游戏时会产生卡顿。这主要取决于你所安装的硬件,驱动程序版本和并行运行的进程(例如,打开多个浏览器标签页可能导致游戏在运行时出现卡顿)。为了避免这种情况,从 3.1 版本开始,Godot 将游戏的优先级提升到了“高于标准”。这样能够相当程度缓解问题,但可能无法完全消除卡顿现象。

完全消除这种情况需要给你的游戏以充分的权限, 使之成为 "time critical" , 这是不建议的. 有些游戏可能会这样做, 但建议学会忍受这个问题, 因为这对Windows游戏来说很常见, 而且大多数用户不会在窗口中玩游戏(反正在窗口中玩的游戏, 如益智游戏, 通常不会出现这个问题).

对于全屏来说,Windows 系统对游戏给予了特殊的优先级,所以卡顿现象不再可见,也非常罕见。大多数游戏都是这样玩的。

When using a mouse with a polling rate of 1,000 Hz or more, consider using a fully up-to-date Windows 11 installation which comes with fixes related to high CPU utilization with high polling rate mice. These fixes are not available in Windows 10 and older versions.

小技巧

游戏应该使用独占全屏窗口模式,而不是全屏,后者旨在防止 Windows 自动将窗口视为独占全屏。

全屏旨在供想要使用每像素透明度而又不存在被操作系统禁用的风险的 GUI 应用程序使用。它通过在屏幕底部留下一条 1 像素的线来实现这一点。相比之下,独占全屏使用实际屏幕大小,并允许 Windows 减少全屏游戏的抖动和输入延迟。

Linux

在桌面 Linux 上可能会出现卡顿现象,但这通常与不同的视频驱动程序和合成器有关。某些合成器也可能引发该问题(例如 KWin),因此建议尝试使用其他合成器以排除其原因。某些窗口管理器(例如 KWin 和 Xfwm)允许你手动禁用合成,这可以提高性能(但代价是撕裂)。

除了向驱动程序或合成器开发人员报告问题外,没有其他方法可以解决驱动程序或合成器卡顿问题。在窗口模式下玩游戏时,卡顿可能比在全屏模式下玩游戏时更严重,即使禁用了合成功能也是如此。

Feral GameMode 可用于在运行特定进程时自动应用优化(例如强制使用 GPU 性能配置文件)。

macOS

通常情况下,macOS 不会出现卡顿现象,尽管最近在全屏运行时报告了一些 bug(这是 macOS 的 bug)。如果你的机器表现出这种行为,请将这问题提交给我们。

Android

通常情况下,Android 平台不会出现卡顿和抖动现象,因为运行活动拥有所有的优先级。也就是说,可能会出现问题的设备(较旧的 Kindle Fire 就是其中之一)。如果你在 Android 平台上看到这些问题,请将问题提交给我们。

iOS

iOS设备通常没有卡顿现象,但运行新版操作系统的旧式设备可能会出现问题。这通常是不可避免的。

输入延迟

项目配置

On platforms that support disabling V-Sync, input lag can be made less noticeable by disabling V-Sync in the project settings. This will however cause tearing to appear, especially on monitors with low refresh rates. It's suggested to make V-Sync available as an option for players to toggle.

When using the Forward+ or Mobile rendering methods, another way to reduce visual latency when V-Sync is enabled is to use double-buffered V-Sync instead of the default triple-buffered V-Sync. Since Godot 4.3, this can be achieved by reducing the Display > Window > V-Sync > Swapchain Image Count project setting to 2. The downside of using double buffering is that framerate will be less stable if the display refresh rate can't be reached due to a CPU or GPU bottleneck. For instance, on a 60 Hz display, if the framerate would normally drop to 55 FPS during gameplay with triple buffering, it will have to drop down to 30 FPS momentarily with double buffering (and then go back to 60 FPS when possible). As a result, double-buffered V-Sync is only recommended if you can consistently reach the display refresh rate on the target hardware.

Increasing the number of physics iterations per second can also reduce physics-induced input latency. This is especially noticeable when using physics interpolation (which improves smoothness but increases latency). To do so, set Physics > Common > Physics Ticks Per Second to a value higher than the default 60, or set Engine.physics_ticks_per_second at runtime in a script. Values that are a multiple of the monitor refresh rate (typically 60) work best when physics interpolation is disabled, as they will avoid jitter. This means values such as 120, 180 and 240 are good starting points. As a bonus, higher physics FPSes make tunneling and physics instability issues less likely to occur.

增加物理 FPS 的缺点是 CPU 使用率会增加,这会导致具有大量物理模拟代码的游戏中出现性能瓶颈。可以通过仅在低延迟至关重要的情况下增加物理 FPS 或让玩家调整物理 FPS 以匹配其硬件来缓解这一问题。但是,不同的物理 FPS 会导致物理模拟的不同结果,即使在游戏逻辑中始终使用 delta。这可以让某些玩家比其他玩家更具优势。因此,对于竞争性多人游戏,应避免允许玩家自己更改物理 FPS。

最后,你可以通过在脚本中调用 Input.set_use_accumulated_input(false) 来禁用每个渲染帧的输入缓冲。这将使脚本中的 _input()_unhandled_input() 函数在每个输入时被调用,而不是累积输入并等待一帧来渲染。禁用输入累积会增加 CPU 使用率,因此应谨慎操作。

小技巧

On any Godot project, you can use the --disable-vsync command line argument to forcibly disable V-Sync. Since Godot 4.2, --max-fps <fps> can also be used to set a FPS limit (0 is unlimited). These arguments can be used at the same time.

针对硬件/操作系统

如果你的显示器支持,请考虑启用可变刷新率(G-Sync/FreeSync)并保持 V-Sync 启用,然后根据该页面将项目设置中的帧速率限制为略低于显示器最大刷新率的值。例如,在 144 Hz 显示器上,你可以将项目的帧速率上限设置为 141。这乍一看可能违反直觉,但将 FPS 限制在最大刷新率范围以下可确保操作系统永远不必等待垂直消隐完成。这会导致相似的输入延迟,就像在帧速率上限相同的情况下禁用 V-Sync 一样(通常不大于 1 毫秒),但不会出现任何撕裂。

This can be done by changing the Application > Run > Max FPS project setting or assigning Engine.max_fps at runtime in a script.

在某些平台上,你还可以在图形驱动程序选项中选择低延迟模式(例如 Windows 上的 NVIDIA 控制面板)。Ultra 设置将为你提供尽可能低的延迟,但平均帧率会略低。强制 GPU 使用最高性能配置文件也可以进一步减少输入延迟,但代价是更高的功耗(以及由此产生的热量/风扇噪音)。

最后,确保你的显示器在操作系统的显示设置中以尽可能最高的刷新率运行。

此外,请确保你的鼠标被配置为使用其最高轮询率(游戏鼠标通常为 1,000 Hz,有时更高)。但是,高 USB 轮询率可能会导致 CPU 使用率过高,因此对于低端 CPU,500 Hz 可能是更安全的选择。如果你的鼠标提供多个 DPI 设置,请考虑`使用尽可能最高的设置并降低游戏内灵敏度以减少鼠标延迟 <https://www.youtube.com/watch?v=6AoRfv9W110>`__。

在 Linux 上,在允许禁用合成的窗口管理器(如 KWin 或 Xfwm)中禁用合成可以显著减少输入延迟。

报告卡顿、抖动或输入延迟问题

如果你报告的卡顿或抖动问题(提交 Issue)不是由上述原因引起的,请尽可能详细说明关于你的设备配置、操作系统、驱动程序版本等信息。这有助于我们更好地排除故障。

如果你要报告输入延迟问题,请附上使用高速相机(例如手机的慢动作视频模式)拍摄的画面。拍摄画面必须同时显示屏幕和输入设备,以便计算输入和屏幕结果之间的帧数。此外,请务必提及显示器的刷新率和输入设备的轮询率(尤其是鼠标)。

此外,请确保根据所表现出的行为使用正确的术语(抖动、卡顿、输入延迟)。这将有助于更快地了解你的问题。提供一个可用于重现该问题的项目,如果可以,请包含演示该 Bug 的屏幕截图。