垂直同步(VSync)
你可以把垂直同步理解为**"游戏向手机屏幕妥协",手机屏幕有一个固定的刷新率。比如大部分普通手机屏幕是 60Hz(一秒钟刷新 60 次画面),好一点的手机是 120Hz。 如果开启了垂直同步(VSync),就等于告诉游戏:"你出图的速度,必须严格配合**屏幕刷新的节奏"。
如果屏幕是 60Hz,开启垂直同步后,游戏最高只能跑 60帧。如果系统判断手机发热降频,跑不满 60 帧了,垂直同步会非常粗暴地把游戏的帧率直接腰斩,也就是强制掉到 30帧。哪怕你当时能跑 55 帧,它为了和屏幕节奏同步,也会硬生生给你降到 30 帧。
那么unity里的api接口是用来干嘛的呢?
Application.targetFrameRate = 30;
在 Unity 引擎的底层规则里:垂直同步(VSync)的优先级 高于 代码锁帧(targetFrameRate)。
所以:
假设一台手机屏幕是 60Hz,同时你开启了垂直同步:
1.场景A:你想锁 120 帧 代码执行:Application.targetFrameRate = 120; 结果:游戏只会跑 60帧。因为垂直同步把帧率上限死死卡在了屏幕的最高刷新率(60Hz)上,你代码写再高都没用。
2.场景B:你想锁 30 帧,但系统强制插手 在一些安卓手机上,由于底层驱动或系统魔改的原因,只要开了垂直同步,系统发现游戏性能良好,可能会无视你的 targetFrameRate = 30,硬生生把帧率拉高去匹配 60Hz 屏幕刷新率,导致你的省电策略(非战斗锁 30 帧)失效,手机反而发热。
3.场景C:你想锁 60 帧,但性能偶尔波动 代码执行:Application.targetFrameRate = 60;。 本来游戏性能可以跑到 58 帧(玩家感受不到明显卡顿)。但因为开了垂直同步,这 58 帧无法和 60Hz 屏幕完美对齐。于是垂直同步机制会触发"腰斩"效应,把你的帧数瞬间降到 30 帧,玩家会感觉突然卡了一下。
垂直同步(VSync)最大的作用就是解决画面撕裂(Screen Tearing),其次是防止显卡过劳(节能降温)。
作用 1:解决"画面撕裂"(最核心的作用)
1.没有垂直同步的时候(自由奔跑): 显卡(渲染画面的老大哥)和屏幕(显示画面的小老弟)是各干各的。 显卡只要一画完一张图,就马上塞给屏幕显示。但问题是,屏幕正在从上往下一点点扫描显示上一张图(还没显示完),显卡突然硬塞进一张新图。 这就导致:屏幕上半截显示的是上一帧的画面,下半截显示的是刚刚塞进来的新一帧画面。因为游戏里的人物和镜头在移动,这两截画面是错位的,玩家就会看到一条明显的横向断层,这就是画面撕裂。特别是当玩家快速转动镜头时,撕裂会非常严重。
2.开启垂直同步之后(排队等候): 相当于给显卡立了个规矩:"你画得再快也没用,必须等屏幕把当前这张图完整显示完了,你才能把下一张图交出去。" 这样屏幕每次显示的都是完整的一帧,画面就变得非常平滑、完整,不再有错位撕裂的现象。
作用 2:防止显卡"空转"(节能、降温)
假设你的屏幕只有 60Hz 的刷新率(一秒只能显示 60 张图)。
如果不开垂直同步,也不用代码锁帧,显卡可能会拼命干活,跑出 120 帧。
多跑出来的那 60 帧,屏幕根本来不及显示,完全是无效的劳动。这会导致手机/电脑疯狂发热、耗电量剧增。
开了垂直同步后,显卡发现屏幕一秒只要 60 张,它跑到 60 帧就会主动停下来休息。这在一定程度上起到了节能和防止设备过热的作用。
既然有用,为什么手游/Unity 经常要关掉它?
对于 PC 主机游戏,尤其是竞技类之外的 3A 大作,通常建议开启垂直同步以获得更好的画面连贯性。但在手游开发中,我们往往倾向于关掉它(把 vSyncCount 设为 0),原因如下:
-
争夺控制权冲突(就是你项目遇到的问题) 像之前提到的,手机的硬件和安卓系统的调度非常复杂。一旦开启垂直同步,帧率的控制权就被操作系统和底层硬件拿走了。你想在战斗外省电锁 30 帧?你想做极致省电模式锁 10 帧?不好意思,系统开了垂直同步可能强制把你拉满,或者在性能波动时疯狂掉帧(比如只能跑 55 帧时被强行锁到 30 帧)。为了让代码里的 Application.targetFrameRate 绝对生效,开发者必须关掉垂直同步。
-
增加输入延迟(操作变"肉") 垂直同步要求显卡等屏幕,这意味着你按下技能键后,画面要多排一会儿队才能显示出来。这就产生了所谓的"输入延迟"(Input Lag)。在要求反应速度的动作游戏或竞技游戏里,玩家会觉得按键"不跟手"、"滑步"。关掉垂直同步能获得最直接的响应速度。
总结
垂直同步的优点:防画面撕裂,使画面平滑。
在你们项目中的弊端:会剥夺代码控制帧率的权限,导致你写的省电逻辑、30/60帧切换逻辑统统失效或行为异常。
所以,常规的手游做法是:关闭垂直同步,然后用代码(Application.targetFrameRate = 60 等)来控制最高帧数,以此来防止手机过热,同时保留对帧率的绝对控制权。 虽然这偶尔会有极轻微的画面撕裂,但在手机那么小的屏幕上,玩家通常很难察觉到。
简单理解:Application.targetFrameRate = 120 ,unity告诉CPU和GPU每秒钟渲染产生出120张图出来,至于屏幕能不能一秒钟画120张图取决于手机屏幕的刷新率,如果这个手机很垃圾,就是它的屏幕刷新率是30Hz,那它每秒钟只能画30张图,如果这种手机上设置了120帧,那么每秒屏幕还是画30张图,多余的90张图就浪费了。所以会白白浪费CPU和GPU的电力和算力,玩家手机会耗电很快,并且很烫,但是并不能带来画面观感上的提升。