Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

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

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

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

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

抖动和卡顿的区分

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

../../_images/motion_normal.gif

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

../../_images/motion_jitter.gif

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

../../_images/motion_stutter.gif

抖动

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

有时只有部分物体会出现抖动(角色或背景)。这是因为它们的更新逻辑在不同的时间源中处理(一个在物理步骤中处理,而另一个在空闲步骤中处理)。

这种抖动问题可以通过在项目设置中启用 物理插值 来缓解。物理插值会在物理帧之间对物体变换进行插值计算,从而平滑物理更新。这样一来,无论帧率和物理更新速率如何,物理对象的视觉呈现都会始终保持流畅。

启用物理插值时,需要注意一些注意事项。例如,在瞬移对象时必须格外小心,避免对象在旧位置和新位置之间出现非预期的插值过渡效果。详情请参阅 物理插值

备注

启用物理插值会增加依赖物理周期的行为(如玩家移动)的输入延迟。多数游戏中,这通常比抖动更可取,但对固定帧率游戏(如格斗/节奏类)需审慎评估。这种输入延迟的增加可以通过提高物理周期更新速率来弥补(参见 卡顿与输入延迟章节)。

卡顿

卡顿可能由多种不同原因引起。其中一个原因是游戏因 CPU 或 GPU 瓶颈而无法维持满帧率性能。解决方法因具体游戏而异,需要参阅 优化

造成游戏卡顿的另一个常见原因是 着色器编译卡顿(shader compilation stutter) 。当游戏里第一次生成某种新的材质或粒子特效时,如果此时需要即时编译对应的着色器,就会发生这种情况。这种卡顿通常只会在第一次游玩时出现,或者是在显卡驱动更新导致着色器缓存(shader cache)失效之后才会发生。

自 Godot 4.4 起,使用 Forward+ 或 Mobile 渲染器时,引擎会通过超级着色器(ubershader)技术减少编译卡顿。为使此方案发挥最大效果,在设计场景和资源时需要加以注意,以便 Godot 能在加载场景/资源时尽可能多地收集信息,而不是等到首次绘制时。更多信息请参阅 管线编译

但使用兼容性渲染器(Compatibility)时,由于OpenGL的技术限制,无法采用超级着色器方案。要避免兼容性渲染器下的着色器编译卡顿,需在关卡加载时将所有网格和视觉效果在摄像机前生成一帧。这样可以确保着色器在加载关卡时完成编译,而不是在游戏进行中才编译。这可以在纯色 2D 界面后方(例如全屏的 ColorRect 节点)进行,让玩家不可见。

备注

在支持禁用 垂直同步(V-Sync)的平台上,通过在项目设置中禁用垂直同步(V-Sync)可以减少卡顿现象。但这会导致出现画面撕裂现象,尤其是在刷新率较低的显示器上。如果你的显示器支持,可以考虑在保持垂直同步(V-Sync)开启的情况下启用可变刷新率(G-Sync/FreeSync)。这样可以在不引入画面撕裂的同时缓解某些形式的卡顿。不过,这对大幅卡顿(例如着色器编译导致的卡顿)并无帮助。

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

此外,卡顿也可能由底层操作系统引起。以下是关于不同操作系统上卡顿的一些信息:

Windows

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

要完全消除卡顿,需要赋予游戏最高权限使其成为“时间关键”(Time Critical)级别,但这并不建议。有些游戏可能会这么做,但建议开发者学会接受这个问题,因为这在 Windows 游戏中很常见,而且大多数用户不会以窗口模式玩游戏(而以窗口模式运行的游戏,如益智游戏,通常根本不会出现此问题)。

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

当使用轮询率为 1000 Hz 或更高的鼠标时,建议使用完全更新至最新版本的 Windows 11,该版本包含与高轮询率鼠标导致的高 CPU 占用相关的修复。这些修复在 Windows 10 及更早版本中不可用。

小技巧

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

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

Linux

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

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

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

macOS

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

Android

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

iOS

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

输入延迟

项目配置

在支持禁用垂直同步的平台上,通过在项目设置中禁用垂直同步,输入延迟可以变得不那么明显。但这会导致出现撕裂现象,尤其是在刷新率较低的显示器上。建议将垂直同步作为一个可切换的开关提供给玩家。

在使用 Forward+ 或 Mobile(移动)渲染方法时,另一种在启用 V-Sync 的情况下减少视觉延迟的方法是使用双缓冲 V-Sync 而不是默认的三缓冲 V-Sync。自 Godot 4.3 起,你可以通过将**项目设置**中的 Display > Window > V-Sync > Swapchain Image Count 减少到 2 来实现这一点。使用双缓冲的缺点是,如果由于 CPU 或 GPU 瓶颈而无法达到显示刷新率,帧率将变得不太稳定。例如,在 60 Hz 的显示器上,如果使用三缓冲时帧率通常会降至 55 FPS,那么使用双缓冲时帧率将暂时降至 30 FPS(然后在可能时恢复到 60 FPS)。因此,仅当你能在目标硬件上 consistently (持续)达到显示刷新率时,才建议使用双缓冲 V-Sync。

增加每秒物理迭代次数也可以减少物理引起的输入延迟。这在使用物理插值(可提高平滑度但会增加延迟)时尤其明显。为此,请将物理 > 通用 > 每秒物理刻数设置为高于默认值 60 的值,或在脚本中运行时设置 Engine.physics_ticks_per_second。当禁用物理插值时,显示器刷新率的倍数(通常为 60)效果最佳,因为它们可以避免抖动。这意味着诸如 120180240 之类的值是很好的起点。作为奖励,更高的物理 FPS 使隧道和物理不稳定问题不容易发生。

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

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

小技巧

在任何 Godot 项目中,你可以使用 --disable-vsync 命令行参数 来强制禁用垂直同步。自 Godot 4.2 起,还可以使用 --max-fps <fps> 来设置 FPS 限制(0 表示无限制)。这些参数可以同时使用。

针对硬件/操作系统

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

这可以通过更改应用 > 运行 > 最大 FPS项目设置或在脚本运行时赋值 Engine.max_fps 来完成。

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

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

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

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

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

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

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

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