一、Unity Vsync 

unity 刷子只读 unity 刷新率_帧率

参考文章:(本文仅做记录,具体思路可以参考原作者描述)

安卓系统中有 2 种 VSync 信号:屏幕产生的硬件 VSync 和由 SurfaceFlinger 将其转成的软件 Vsync 信号。后者经由 Binder 传递给 Choreographer。 

           关闭Vsync ,采用单缓存工作流程,如图:

unity 刷子只读 unity 刷新率_帧率_02

如上图,CPU/GPU 向 Buffer 中生成图像,屏幕从 Buffer 中取图像、刷新后显示。这是一个典型的生产者——消费者模型。 
理想的情况是帧率和刷新频率相等,每绘制一帧,屏幕显示一帧。而实际情况是,二者之间没有必然的大小关系,如果没有锁来控制同步,很容易出现问题。例如,当帧率大于刷新频率,当屏幕还没有刷新第 n-1 帧的时候,GPU 已经在生成第 n 帧了,从上往下开始覆盖第 n-1 帧的数据,当屏幕开始刷新第 n-1 帧的时候,Buffer 中的数据上半部分是第 n 帧数据,而下半部分是第 n-1 帧的数据,显示出来的图像就会出现上半部分和下半部分明显偏差的现象,我们称之为 “tearing”,如下图: 

unity 刷子只读 unity 刷新率_unity 刷子只读_03

双重缓存(Double Buffer)

注意,此处的“双缓冲”和计算机组成原理中的“二级缓存”是两回事。三重缓存也是如此。 
为了解决单缓存的“tearing”问题,双重缓存和 VSync 应运而生。双重缓存模型如下图: 

unity 刷子只读 unity 刷新率_缓存_04

两个缓存区分别为 Back Buffer 和 Frame Buffer。GPU 向 Back Buffer 中写数据,屏幕从 Frame Buffer 中读数据。VSync 信号负责调度从 Back Buffer 到 Frame Buffer 的复制操作,可认为该复制操作在瞬间完成。其实,该复制操作是等价后的效果,实际上双缓冲的实现方式是交换 Back Buffer 和 Frame Buffer 的名字,更具体的说是交换内存地址(有没有联想到那道经典的笔试题目:“有两个整型数,如何用最优的方法交换二者的值?”),通过二位运算“与”即可完成,所以可认为是瞬间完成。

双缓冲的模型下,工作流程这样的: 
在某个时间点,一个屏幕刷新周期完成,进入短暂的刷新空白期。此时,VSync 信号产生,先完成复制操作,然后通知 CPU/GPU 绘制下一帧图像。复制操作完成后屏幕开始下一个刷新周期,即将刚复制到 Frame Buffer 的数据显示到屏幕上。

在这种模型下,只有当 VSync 信号产生时,CPU/GPU 才会开始绘制。这样,当帧率大于刷新频率时,帧率就会被迫跟刷新频率保持同步,从而避免“tearing”现象。

注意:当 VSync 信号发出时,如果 GPU/CPU 正在生产帧数据,此时不会发生复制操作。屏幕进入下一个刷新周期时,从 Frame Buffer 中取出的是“老”数据,而非正在产生的帧数据,即两个刷新周期显示的是同一帧数据。这是我们称发生了“掉帧”(Dropped Frame,Skipped Frame,Jank)现象。

总结:带下划线的位置,就是博主遇到的开启垂直同步,会引起帧率轻微波动的原因。

           方案,关闭垂直同步,同时控制帧率。

二、Camera  个数(尽可能的少,或者在不用时,禁用掉)

        每个Camera 都会走Camera.Render ,即使没有渲染任何东西,也会Culling(锥形范围视口剔除操作)

        其次,减少场景内的物体数量,能有效降低SceneCulling的消耗。