Unity 垂直同步(VSync)和帧率

VSync 术语

垂直同步 (VSync, Vertical Synchronization) 是一种显示设置,可以限制游戏的帧率来匹配显示器的刷新率,以防止图像撕裂。

参考:https://docs.unity3d.com/cn/2019.4/Manual/Glossary.html

工程设置

Unity 的 VSync 设置位于 Project Settings -> Quality -> VSync Count

V Sync Count

选择将渲染与垂直空白同步还是根本不同步。Unity 可将渲染与显示设备的刷新率同步来避免撕裂瑕疵。可用选项包括 Every V BlankEvery Second V BlankDon’t Sync

参考:https://docs.unity3d.com/cn/2019.4/Manual/class-QualitySettings.html

画面撕裂问题

显示设备上的图片不会持续更新,而是定期更新,很大程度上就像 Unity 中的帧更新一样。但是,Unity 的更新不一定与显示器的更新同步,因此 Unity 有可能在显示器仍在渲染前一帧时发出新的帧。这会导致在屏幕上发生帧变化的位置处产生称为 “撕裂” 的视觉瑕疵。

模拟撕裂的示例。在放大的部分有清晰可见的图像偏移。

可以使 Unity 仅在显示设备未更新的时间段(即所谓的“垂直空白”)切换帧。Quality 设置中的 V Sync Count 选项将帧开关与设备的垂直空白同步,还可以选择与每隔一个垂直空白同步。如果游戏需要多个设备更新来完成帧的渲染,后者可能会很有用。

参考:https://docs.unity3d.com/cn/2019.4/Manual/class-QualitySettings.html

QualitySettings.vSyncCount

垂直同步数。

应在每帧之间传递的垂直同步数。使用 “Don’t Sync” (0) 则不等待垂直同步。 值必须为 0、1、2、3 或 4。

如果此设置被设置为 非 “Don't Sync”(0),则将忽略 Application.targetFrameRate 的值。

注意:这在 iOS 上不适用,在 iOS 上会忽略 VSync 设置。在 iOS 上,设备在 VBlank 上显示帧。如果因设置的 Application.targetFrameRate 或性能低而缺失 VBlank,则帧显示在下一个上。

1
2
3
4
5
6
7
8
9
10
using UnityEngine;

public class Example : MonoBehaviour
{
void Start()
{
// Sync framerate to monitors refresh rate
QualitySettings.vSyncCount = 1;
}
}

参考:https://docs.unity3d.com/cn/2019.4/ScriptReference/QualitySettings-vSyncCount.html

Application.targetFrameRate

指示游戏尝试以指定的帧率渲染。

默认的 targetFrameRate 是一个特殊值 -1,表示游戏应以平台的默认帧率渲染。此默认速率取决于平台:

  • 在独立平台上,默认帧率是可实现的最大帧率。
  • 在移动平台上,由于需要节省电池电量,默认帧率小于可实现的最大帧率。移动平台上的默认帧率通常为每秒 30 帧。
  • 所有移动平台可实现的最大帧率都有固定上限,这等于屏幕的刷新率(60 Hz = 60 fps,40 Hz = 40 fps,…)。Screen.currentResolution 包含屏幕刷新率。
  • 此外,所有移动平台都只能在 VBlank 上显示帧。因此,应将 targetFrameRate 设置为 -1,或是等于屏幕刷新率的值,或是刷新率除以一个整数。否则,生成的帧率始终小于 targetFrameRate。注意:如果将 targetFrameRate 设置为刷新率除以一个整数,则整数除法得到的有效 fps 与将 QualitySettings.vSyncCount 设置为相同整数值时相同。
  • iOS 会忽略 QualitySettings.vSyncCount 设置。相反,设备会在帧准备就绪之后的第一个可能 VBlank 上显示帧,应用程序会实现 /targetFrameRate/。
  • 在 WebGL 上,默认值允许浏览器选择帧率来匹配其渲染循环时序,这通常会产生最平滑的效果。只有当您想要限制 WebGL 上的 CPU 使用率时,才建议使用非默认值。
  • 使用 VR 时,Unity 将使用 SDK 指定的目标帧率并忽略游戏指定的值。

设置 targetFrameRate 不保证会实现帧率。由于平台规格不同,帧率可能会出现波动,或者由于设备速度太慢,游戏可能无法达到帧率。

此外,如果设置了 QualitySettings.vSyncCount 属性,将忽略 /targetFrameRate/,而游戏将使用 vSyncCount 和平台的默认渲染率来确定目标帧率。例如,如果平台的默认渲染速率为每秒 60 帧且 vSyncCount 设置为 2,则游戏将以每秒 30 帧为目标。

在编辑器中,targetFrameRate 仅影响 Game 视图。不会影响其他编辑器窗口。

1
2
3
4
5
6
7
8
9
10
using UnityEngine;

public class Example
{
void Start()
{
// Make the game run as fast as possible
Application.targetFrameRate = 300;
}
}

参考:https://docs.unity3d.com/cn/2019.4/ScriptReference/Application-targetFrameRate.html

垂直同步对 FPS 的影响

我们平时运行操作系统一般屏幕刷新率是多少?大概一般都是在 60Hz 左右,那么显卡就会每按照 60Hz 的频率时间来发送一个垂直同步信号,信号和信号的时间间隔是上两次屏幕更新的时间间隔。

如果我们选择等待垂直同步信号(也就是我们平时所说的垂直同步打开),那么在游戏中或许强劲的显卡迅速的绘制完一屏的图像,但是没有垂直同步信号的到达,显卡无法绘制下一屏,只有等 60Hz 单位的信号到达,才可以绘制。这样 FPS 自然要受到操作系统刷新率运行值的制约。

而如果我们选择不等待垂直同步信号(也就是我们平时所说的关闭垂直同步),那么游戏中作完一屏画面,显卡和显示器无需等待垂直同步信号就可以开始下一屏图像的绘制,自然可以完全发挥显卡的实力。但是不要忘记,正是因为垂直同步的存在,才能使得游戏进程和显示器刷新率同步,使得画面更加平滑和稳定。取消了垂直同步信号,固然可以换来更快的速度,但是在图像的连续性上势必打折扣。这也正是很多朋友抱怨关闭垂直后发现画面不连续的理论原因。

参考:https://blog.csdn.net/iningwei/article/details/104653210

知识补充:刷新率

刷新率是指电子束对屏幕上的图像重复扫描的次数。刷新率越高,所显示的图象(画面)稳定性就越好。刷新率高低将直接决定其价格,但是由于刷新率与分辨率两者相互制约,因此只有在高分辨率下达到高刷新率这样的显示器才能称其为性能优秀。

你可以这么理解,刷新率就是屏幕每秒画面被刷新的次数,看电影时我们看到的其实是一副一副静止的画面,就像放幻灯片,为什么我们感觉画面在动,那是因为人的眼睛有视觉停留效应,前一副画面留在大脑中的印象还没消失,紧接着后一副画面就跟上来了,而且两副画面间的差别很小,一个动作要用很多副画面来显示,这样我们就感觉画面在动了,这一副一副的更换画面,就是在刷新,假设一个动作由20张画面完成,我们看上去就有点象动画片,而这个动作增加到30张的话,看上去就自然多了,这就是刷新率。

参考:https://baike.baidu.com/item/刷新率

知识补充:赫兹单位

赫兹是国际单位制中频率的单位,它是每秒钟的周期性变动重复次数的计量。

赫兹简称赫。每秒钟振动(或振荡、波动)一次为1赫兹,或可写成次/秒,周/秒。因德国科学家赫兹而命名。

参考:https://baike.baidu.com/item/赫兹/7245576