Unity垂直同步:帧率和刷新率
帧率(英语:frame rate)是用于测量显示帧数的度量。测量单位为“每秒显示帧数”(frame per second,FPS)或“赫兹”,一般来说FPS用于描述视频、电子绘图或游戏每秒播放多少帧。
显示器的刷新率是指显示器每秒绘制新图像的次数。其单位为赫兹 (Hz)。例如,如果您的显示器刷新率为 144 Hz,这是指它每秒钟会刷新图像 144 次。
帧率直接依赖于显卡的输出速度,跟渲染速度有关,取决于CPU和GPU侧的性能,GPU瓶颈和GPU瓶颈都会导致帧率下降。
本质上说,帧率和刷新率类似于生产者消费者这种同步关系,理想情况下两者保持同步,但实际大多数时候都没法做到。刷新率由硬件决定,当帧率相比刷新率过大或者过小都会产生问题。
同步问题
在FPS小于刷新率的情况下,显卡无法在下一次刷新之前输出一帧,那么它将重复上一帧并等待下一次刷新。但是显卡的输出频率是不均衡的,会在一个比较大的范围波动,这会导致帧在某些时候重复,但在其他时候不重复。这会导致输出结果不均匀,产生奇怪的卡顿。
在FPS大于刷新率的情况下,此时又会产生屏幕撕裂的问题:由于显卡输出的频率大于显示器刷新频率,此时有多个帧同时占据屏幕的各个部分,会造成屏幕撕裂。
垂直同步V-Sync
在FPS小于刷新率的情况下,此时因为开启了垂直同步,显卡会让帧率稳定频率输出。为了保持显示器显示均匀,通常输出频率会是刷新率的1/N,也就是说显示器每隔N帧获取一次显卡输出,其他N-1帧重复上一帧,这样输出结果是均匀的观感上好一些。
举个例子,屏幕刷新率是144Hz,N=2~10时屏幕FPS依次为:72,48,36,28.8,24,20.6,18,16,14.4。在开启垂直同步时,FPS只会取这些离散值,但实际会发现FPS会介于这些离散值之间,这是因为FPS是一秒内的宏观统计值,假设半秒是36,半秒是24,那么FPS就是平均值30。
在FPS大于刷新率的情况下,开启垂直同步意味着FPS于屏幕刷新率同步,此时FPS被强制设定为屏幕刷新率,这样解决了画面撕裂的问题。但此时也引入了另一个问题——输入延迟。其实就是由于限制了显卡输出速度导致的延迟, 在高精度和快速移动的部分很明显。
自适应同步
自适应同步(adaptive-sync)是指让显示器按照帧率显示的技术,比如NVIDIA的G-Sync和AMD的FreeSync。需要显示器硬件支持,并且条件是显示器最低刷新率<FPS<显示器最高刷新率。这也很好理解,实现的效果就是显示器不再丢弃任何一帧。
Unity垂直同步
在Play Mode时,可以点击Free Aspect下拉选择VSync打开垂直同步,可以看到会限制此时FPS会到刷新率144Hz:
关闭垂直同步时,帧率到了400FPS。这只代表GPU端的输出频率,输出到屏幕上仍然是144Hz。
当渲染压力增大时帧率降低,如果开启了垂直同步,那么此时会在离散值附近小范围波动,如下是N=10的情况,这时FPS=14.4。
但是如果没有开启垂直同步,FPS变化范围很大而且值是随机变化的:
值得一提的是,Unity提供的FPS值并不一定准确,它的计算方式上只考虑了CPU侧的性能(包括使用Time.unscaledDeltaTime接口计算的FPS),而并非显示器的展示帧率。微观角度上会有误差,但是在宏观角度上比较接近。