- 最后登录
- 2019-12-25
- 注册时间
- 2012-8-24
- 阅读权限
- 90
- 积分
- 71088
 
- 纳金币
- 52344
- 精华
- 343
|
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分享
|
|