1.OverDraw简介
2.Unity 中如何查看 OverDraw
3.优化OverDraw
1.OverDraw简介
csharp
复制代码
1).OverDraw定义
OverDraw表示GPU在同一帧内, 对屏幕上的同一个像素位置, 绘制了超过1次
可以用画画做比喻: 你在一张纸上画一幅画, 正常情况是一个位置只涂一次颜料(1次绘制, 无OverDraw)如果先涂红色、再在
红色上面涂蓝色, 最后再涂黄色(同一个位置涂3次), 那这个位置的OverDraw次数就是3次
关键前提:
a.不透明物体默认不会产生OverDraw, GPU有深度测试/深度剔除机制, 先画的不透明物体会占据像素的深度信息, 后画的不透
明物体如果在该像素背后, 会被直接剔除, 不绘制
b.OverDraw的核心来源是"透明/半透物体", 比如: UI、粒子、透明特效、半透材质等, 因为透明物体GPU会关闭深度剔除, 要
看到背后的物体, 必须先画背后的, 再画前面的透明物体, 叠着画
csharp
复制代码
2).OverDraw的核心危害
GPU的渲染能力有一个关键指标: "填充率即GPU 每秒能绘制的像素总数", 这是固定资源, 就像水管的最大出水量
OverDraw本质是"浪费GPU的填充率": 同一个像素画多次, 相当于水管往同一个杯子里反复加水, 其他杯子(屏幕其他像素)就
没水了, 最终导致
a.帧率下降: 填充率被占满, GPU处理完一帧的时间变长, 游戏掉帧
b.设备发热/功耗增加: GPU持续满负载工作, 尤其移动端电池容量有限, 发热会直接影响体验
c.高端机无感, 低端机卡顿: 高端机GPU填充率高, 少量OverDraw看不出影响; 但移动端中低端机/老设备填充率低, 轻微的高
OverDraw就会明显卡帧
2.Unity 中如何查看 OverDraw
csharp
复制代码
Unity提供了可视化的OverDraw查看工具, 能直接在Scene视图看到屏幕每个像素的绘制次数,
a.实操步骤
- 打开Unity的Scene视图
- 点击Scene视图右上角的渲染模式下拉框
- 选择OverDraw模式, 即可切换到过度绘制可视化界面
b.颜色对应绘制次数
Scene视图中不同颜色代表该像素的绘制次数, 颜色越深/越红, OverDraw越严重, 蓝色是理想状态
csharp
复制代码
如果需要数值化统计(如整屏平均OverDraw次数、某一区域的具体次数), 用Unity的Profiler性能分析器
a.顶部菜单栏"Window -> Analysis -> Profiler"
b.选择Rendering模块, 在统计面板中找到OverDraw相关指标(如"Average OverDraw"整屏平均过度绘制次数)
c.可结合"Frame Debugger"帧调试器, 逐步查看每一次绘制的对象, 定位高OverDraw的源头
3.优化OverDraw
csharp
复制代码
1).精简透明/半透明元素(最大元凶)
透明/半透明物体(UI、粒子特效、玻璃、特效贴图)是Overdraw的"重灾区", 因为透明物体不会遮挡后面的像素, GPU会把透明
物体和后面的内容都画一遍
a.UI优化: 别让UI元素多层重叠, 比如3-4层按钮叠在一起, 尽量合并UI, 比如把多个小UI做成一个图集, 删掉看不见的UI,比
如被遮挡的弹窗
b.粒子特效优化: 减少粒子数量比如从100个减到50个, 缩小粒子大小, 降低粒子重叠度
c.材质替换: 能不用透明材质就不用, 比如UI背景用纯色不透明, 别用带透明度的图片
csharp
复制代码
2).让GPU不画看不见的东西(剔除优化)
游戏里很多物体玩家根本看不到, 比如角色背后的墙、相机视野外的树, 没必要让GPU画它们
a.视锥剔除(默认开启): Camera会自动不渲染视野外的物体, 别手动关掉这个功能
b.遮挡剔除(Occlusion Culling): 烘焙场景后, Unity会自动识别"被挡住的物体"并停止渲染, 比如关上门后, 门后的柜子
就不画了
操作: Window -> Rendering -> Occlusion Culling, 点击"Bake"烘焙场景数据即可
c.合并小物体: 把场景里一堆小物体(比如石子、小草)合并成一个 Mesh, 减少重叠绘制的同时还能减少Draw Call
csharp
复制代码
3).调整渲染顺序: 先画不透明, 后画透明
不透明物体(墙、地面、角色)先画: GPU画完不透明物体后, 会知道"被挡住的像素不用再画了", 后续透明物体只画没被挡住
的部分
透明物体(玻璃、特效)后画: 避免透明物体先画, 导致后面的不透明物体还要再画一遍