【YH Multi UI】- 最简单粗暴的《DrawCall优化方案》

YH Multi UI

此贴给大家带来的是一个 非常简单粗暴的一个 DrawCall优化方案,文笔较差,大佬们凑合看

先看图

==》

DrawCll 从 27 到 3

==》

DrawCll 从 58 到 5

这里面还包含调试信息所占用的1个DC。

好,怎么做优化的呢,大佬们对这方面肯定都是很有心得的,论坛上也有各类的优化方案

而我只需要10秒钟,4步,简单粗暴。

  • 1.导入插件

  • 2.初始化

  • 3.点击操作转换UI

  • 4.预览

正常的优化方案我可以通通不使用就能达到这个效果!

  • 不需要修改代码逻辑

  • 不需要调整预制结构

  • 不需要调整图集

DrawCall优化全都由插件代码完成

这个界面仅仅需要2个DC

而这个界面结合了各种Label,只需要5个DC

里面可以查看对比,全都是普通界面制作完成后由插件一键转换完成的。

想看演示地址,这里可以直接查看

接下来简单介绍一下插件

YH Multi UI

插件由来

众所周知,DrawCall一直是影响游戏性能一个关键点。

论坛上也有各位大佬分享的 DrawCall优化方案

目前一般的解决方案是,图集 + Bmfont,配合场景节点结构优化,可以大幅度降低DrawCall。

但是Bmfont如果不和使用的图在一张图集里的话,还是存在Label打断DC的情况

而且图集之间也难免会有重叠,稍不注意就会多出n个DC。

尤其是在一些复杂的UI需求下,DrawCall还是会居高不下

在看到大佬分享的 《江南百景图》多纹理合批方案后,不得不佩服 大佬终究是大佬

如此多图集的相互之间产生的DC就能大大减少了。

然后最近灵光乍现,发现默认cc.Labelcc.Sprite所用的材质 Material 是一样的,那么配合 多纹理合批,是不是完全解决合批的问题。

实现过程

于是我开始研究引擎源码以及《江南百景图》的实现方式。

发现 cc.Labelcc.Sprite 使用的顶点数据格式是 完全一致的,或者说大部分渲染组件用的顶点数据格式是一致的

所以为什么Label会打断渲染,因为普通的Label在渲染的时候,相当于会生成一张图,所以一个Label就是一个DC,而其他类型的Label处理方式就不太一样了,比如 BMFont,因为本身就是从一张Texture里读取的,所以相互之间就可以合批。

而《江南百景图》的 多纹理合批方案,核心其实是修改 检测合批方法,由 判断是否在同一张图集,转为 判断是否在同一批图集

如果将Label的Material与Sprite的Material一致,修改Label的顶点数据,将Label使用的图集也同样传递给Material,让Label也可以使用多纹理合批方案,那么Label就可以与Sprite合批。

到这里都是我的猜想,真正是不是这样子,还得动手试试。

然后。。。漫长的读 引擎源码试验,修Bug,做兼容,真是太难了。。。

方案核心是 多图集合批 + 动态合图 + 自定义顶点格式

于是 MultiUI 出来了,目前只支持MultiSpriteMultiLabel,继承于cc.Spritecc.Label,大部分常用的功能都测试正常。

无论场景节点顺序多么乱,图集多么复杂,MultiUI都能最大限度的降低DrawCall

无需修改任何代码逻辑,使用也相当粗暴无脑,也很符合我当时对这个的构想。

正常继承引擎组件,编辑器显示都有点不正常,这里我都做了兼容,拖到编辑器里无任何差别。

只要使用 MultiUI,就会自动做合批逻辑,可以游戏整体使用,也可以在部分DC较高的界面使用。

插件特点

恬不知耻的说,这是目前最简单粗暴的DrawCall优化方案

简单的游戏,一个游戏一个DC,完全不是问题

为什么说最简单最粗暴呢,除了无需修改任何代码逻辑以外。

其他的优化方案,都是告诉你怎么去优化,怎么才能降低DC。

而MultiUI不一样,你甚至可以不用关心怎么去实现,怎么去优化,你直接用,自然DC就降下来了!

而且支持 一键转换

插件默认提供操作:

  • 转换MultiUI
    
  • 将 cc.Sprite 转换为 MultiSprite
    
  • 将 MultiSprite 转换为 cc.Sprite
    
  • 将 cc.Label 转换为 MultiLabel
    
  • 将 MultiLabel 转换为 cc.Label
    

直接右键选中资源(场景 预制 或文件夹),选择需要进行的操作

【选中】 需要转换的 场景预制体文件夹 ,【右键】运行对应的操作

这些操作,可以帮你快速转换组件!

转换MultiUI,选中资源 后,点击运行,待操作完成后,该资源内的cc.Sprite 与cc.Label,都被转换成MultiUI了

有了一键转换,那就更粗暴了,前期可以完全不用,游戏开发完成之后,或者现在已经有个游戏了。

游戏需要优化,那么导入插件初始化,对需要优化的文件夹一键转换,DrawCall就已经优化完成了。

除此之外,默认预留了3个参数,可作为Shader参数传递,且不会像Material传递参数一样打断渲染合批。

目前默认是用于HSL,如演示案例。

注意事项

当然DrawCall的降低不是没有代价的。

首先渲染的顶点数据格式改了,需要填充与传递的数据变多了。

其次shader内对使用图集的判断次数,也是不可控的。

如果节点可以不使用color,可以考虑将改动的顶点数据,占用color的数据位,或者与color公用,这个可以自己去扩展了。

使用前注意对项目进行备份,以免出现不必要的数据丢失

后续版本计划

  •   1.看能不能支持骨骼合批
    
  •   2.兼容适配3.x
    
  •   3.考虑增加 性能模式,减少顶点数据,降低性能开销
    

插件地址

插件已上传到Cocos商店

1.0.2版本更新内容:
1.支持RichText (尝鲜版,因内部实现会有错误提示,不影响使用,后期版本优化)

67赞

不明觉厉,前排mark

大佬6666,膜拜。

不错阿,有点东西,最近正好研究渲染流程

战术Mark

我滴龟龟,膜拜大佬

膜拜大佬,mark

mark!

大佬啊 顶礼膜拜

大佬厉害了

这也太顶了吧!

强啊:ox:哇大佬

那个demo 不太复杂,图片像素比较高复杂界面呢

mark!!!

不明觉厉,前排mark。狗进YYDS

前排留名,大佬牛批.

请问出现如下报错怎么处理?
每一个用到sprite的地方都变成了missingScript

初始化未成功导致的,这个问题在新版本已经解决,在审核版本了

好的 更新太及时了!

来个复杂界面的压力测试吧.这个方案之前也实现过,试了下500个帧动画,总共图是2048X2048X8,用垃圾手机测试
优化前: dc 几百,fps 35
优化后: dc 2,fpx 30
不知道楼主方案有没有更好的实现.