查看: 2705|回复: 2

[经验分享] UGUI减少DrawCall及CPU和GUP的优化

[复制链接]
may    

8830

主题

80

听众

7万

积分

首席设计师

Rank: 8Rank: 8

纳金币
52296
精华
343

最佳新人 热心会员 灌水之王 活跃会员 突出贡献 荣誉管理 论坛元老

发表于 2018-7-29 00:33:33 |显示全部楼层

UGUI的性能从三方面来优化
1、减少DrawCall(也是一种GUP优化)
2、从CPU方面优化
3、从GUP方面优化

1.DrawCall方面:
UGUI提供一个图集的功能。把零碎的图片打包成一张大图。在使用的时候。读取大图里的数据。这样便于压缩图片占用的内存和减少DrawCall的消耗
UGUI会把相邻的同一图集的图片合并。从而达到减少DrawCall的效果
根据以上信息,可以得到图集分配的一些规则:
1、同一界面的元素,尽量放到一个图集里面
2、同一界面的元素分别在多个图集里面时。尽量把相同图集的元素放在一起。避免图集直接的交叉布置
3、通用的元素,放到一个或者几个共享的图集里面。这样便于降低加载时间
4、如果可以。把带透明通道的和不带透明通道的图片放在不同的图集。(这样可能会产生更多的DrawCall,所以在内存压力大,而GUP压力不大的时候可以这么处理)

2、CPU的优化:
1、内存的优化:上一章 “UGUI图片格式”中讲述了在不同平台上用不同的压缩格式及图片的大小问题
2、删除不用的UI节点、动画组件及资源:在项目迭代的时候。可能有部分UI节点、动画、特效等资源失效。有些时候为了方便。直接把不用的东西隐藏掉。这样虽然看不见了。但是增加了内存和加载时间。所以不用的资源。一定要删除而不是隐藏
3、Canvas.SendWillRenderCanvases或Canvas.BuildBatch占用过多的时间问题
在UI元素的大小、Color等属性发生改变时。Canvas会调用Canvas.SendWillRenderCanvases并且执行Canvas.BuildBatch。在Canvas中UI Mesh的顶点多的话。Canvas.BuildBatch将会出现较高的CUP消耗,
Canvas.BuildBatch是合并Canvas下UI的Mesh。并缓存起来。在Canvas下UI Mesh发生改变时。才会重新合并,Canvas.SendWillRenderCanvases的执行流程如下:

由CanvasUpdateRegistry监听SendWillRenderCanvases事件(图中1)。
1.进行深度排序(图中2)。
2.rebuild Layout。计算各元素的位置和大小
3.rebuild graphic。调用UpdateGeometry进行重建网格数据,UpdateMaterial更新材质信息
基于上面的网格更新原理,有一下几点建议:
1、使用尽可能少的UI元素。这里指的是删除不必要的节点和隐藏不用的节点。这样能减少深度排序和rebuild Layout的执行时间
2、尽量减少Rebuild的频率,将动态和静态的元素分离,放到不同的Canvas里面。
3、谨慎使用Text的Best Fit选项。这个选项可以动态调整字体大小以适应UI布局而不会超出边框,但是代价很高。Unity会为改元素用到的字号生成图元保存的Atlas里面,不但增加了额外的生成时间。还使字体的atlas变大
4、谨慎使用Canvas的Pixel Perfect选项,该选项会使得ui元素在发生位置变化时,造成layout Rebuild。(比如ScrollRect滚动时,如果开启了Canvas的pixel Perfect,会使得Canvas.SendWillRenderCanvas消耗较高)
5、除了Rebuild之外,UGUI处理Touch事件也可能成为性能热点。对应不需要接受输入的元素。一定要关闭Raycast Target选项

3、GUP的优化
一般来说。造成GPU的性能瓶颈一般在复杂的shader和overdraw造成的像素填充过多。一般都是用默认的UI材质。所以从overdraw方面考虑。overdraw主要是因为大量的UI重叠引起的。查看overdraw比较简单。在scene窗口选择overdraw模式。场景中越亮的地方。表示overdraw越高
降低overdraw可以做如下优化:
1、禁用开不见的UI。在被别的UI全部挡住时。可以考虑将系统禁用
2、不要使用空的Image,在Unity项目中。因为要用RayCast使用Graphi作为基本元素来检测touch。很多时候会用空的Image并将alpha设置为0来接收touch事件。这样会产生不必要的overdraw
可以使用一下脚本。只监听事件。不画网格

public class NoDrawingRayCast : Graphic
{
public override void SetMaterialDirty()
{
}

public override void SetVerticesDirty()
{
}

protected override void OnPopulateMesh(VertexHelper vh)
{
vh.Clear();
}
}

用RectMask2D替换Mask。这样会节约两个DrawCall。

以上就是UGUI的性能方面的总结。性能的优化是在各种选择直接做一个适合自己项目的平衡。


来自 sheng2008分享
回复

使用道具 举报

0

主题

2

听众

596

积分

初级设计师

Rank: 3Rank: 3

纳金币
10
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

发表于 2018-8-24 17:19:06 |显示全部楼层
谢谢......这很有帮助。 你真棒
回复

使用道具 举报

0

主题

6

听众

834

积分

初级设计师

Rank: 3Rank: 3

纳金币
114
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

发表于 2019-2-7 10:44:49 |显示全部楼层
谢谢分享!!!学到了!!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

关闭

站长推荐上一条 /1 下一条

手机版|纳金网 ( 闽ICP备08008928号

GMT+8, 2024-3-29 09:39 , Processed in 0.084352 second(s), 29 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部