显示器有一个属性叫屏幕刷新频率,它是指每秒刷新屏幕的次数,单位为Hz,一般设置为60Hz。

从屏幕刷新频率到Unity VSync-风君雪科技博客

什么是刷新屏幕呢?我们屏幕是由像素矩阵组成的,其(CRT)显示图像的原理是靠电子束从左到右、从上到下逐行激发屏幕内表面的荧光粉单元(像素)来实现的。电子束一次水平方向的扫描叫行扫描,一次完整的扫描就是刷新屏幕,形成的图像就是一帧。因此60Hz的刷新率也就是每秒60帧,人眼的视觉暂留需要满足每秒24帧及以上。

显示器扫描的过程中有两个重要的概念:HBlank(行消隐)和VBlank(场消隐)。HBlank是指当行扫描到最右端时需要快速返回到下一行的最左端的过程。而VBlank则是指扫描完一帧,准备开始扫描下一帧,扫描线从右下角返回到左上角的过程。这两个过程的时间间隔中,扫描线需要变得blank,以防止看到一条斜线显示在屏幕上。

游戏渲染中的VSync(垂直同步)技术就与刷新率和VBlank有关。先说说为什么需要VSync。一般情况下CPU执行游戏逻辑和GPU执行渲染的计算都会快于屏幕的刷新,也就是CPU提交渲染数据和命令到GPU、GPU填充渲染结果到显存的速度会快于屏幕刷新,因此当屏幕刷新进行的过程中很可能会出现显存内容被改变的情况,从而造成Tearing(画面撕裂)。

从屏幕刷新频率到Unity VSync-风君雪科技博客

解决Tearing问题的方案就是VSync。前面提到屏幕刷新的两帧之间会有一个VBlank,这个间隔硬件就会产生一个VSync的信号,游戏可以在只有收到该信号后再去计算下一帧,这样就能避免Tearing。实际上,即使在不使用VSync且不会发生Tearing的情况下,由于屏幕刷新率的限制,CPU/GPU的帧率再快对于渲染结果来说并没有影响,反而是一种冗余计算的浪费。而关闭VSync的好处是可以更快的响应输入。

Unity在Quality Settings中有个VSync Count属性可以设置VSync,分别是Don’t Sync(关闭VSync)、Every VBlank(每个VBlank计算一帧)、Every Second VBlank(每两个VBlank计算一帧)。 https://docs.unity3d.com/Manual/class-QualitySettings.html

从屏幕刷新频率到Unity VSync-风君雪科技博客

VSync是需要图形API(DirectX、OpenGL)支持的,Unity对于关闭了VSync或者VSync的设置不被支持的情况采用了在CPU上同步的方案来维持目标帧率:

从屏幕刷新频率到Unity VSync-风君雪科技博客

void TimeManager::Sync (float framerate)中传入目标帧率framerate,函数中通过Sleep和循环来控制每帧的耗时,从而控制帧率。