前言:拼UI相信每个Unity程序都做过的事,也是普遍认为最简单、最入门、最没有技术的工作。不出意外的情况下,都会做出策划需要的效果,但是功能实现了,真的就是正确的吗?或者说真的就是合理的吗?那就不一定了。
Unity的优化不简单的归咎于改一行代码,更改一个参数或者勾选一个选项就会发生质的变化,如果真的是这样,无非两种,官方出了新的功能,或者在开发中有很不合理的地方。
优化的本质其实就是本着能省就省,量身定做,只有保持匠心精神,成系统的优化,才能在性能上有优异的表现。从资源(图片,模型等)进到工程到的那一刻起,就应该保证他是符合规范或者可控,只有在层层的有规范的检查下,才能最大限度保证出包的品质和减少无谓的加班~~~
只有把地基打好,才能稳定层层叠加,下面是笔者整理关于拼UI相关的注意事项,希望能够帮到大家
其他优化点会陆续添加
有说的不正确或者不准确的地方欢迎留言指正
主要参考如下:
Unity版本 2018.4.0f1
示例工程下载
准备工作,先打开Sprite Packer中的Mode
如果要 Sprite Atlas合批设置成 Always Enabled (Legacy Sprite Packer)
1. 设置图集的图片可以合批
2. 避免不同图集或材质的倾轧,Scene视图调节为Writeframe模式可以更容易查看
3. 倾轧时,在Hierarchy视图中排序错误,导致合批的步骤增加
4. Mask会增加一个Draw,并且Mask里面的图片不会和外面的图片合批
5. RichText会造成三角面增加
6. 空的Image造成一个Drawcall并且会打断合批
7. 颜色渐变和可以用material控制,本质是更改Tint属性,这样既能满足颜色渐变,又能避免网格频繁重建造
8. 接受射线脚本:Empty4Raycast
使用的此脚本可以在有效接受点击事件的情况下,不增加drawcall和打断合批
9. 减少OverDraw脚本:PolygonImage
10. 关闭不需要的Raycast Target选项(Image、Text、RawImage),降低每帧检测射线的性能消耗。检测勾选Raycast Target脚本 :DebugUILine
11. 用多个Canvas将屏幕划分出不同的区域,降低网格重建带来的性能损耗
12. 避免或者降低赋值的操作,降低网格重建频率 例如在Update中执行textComponent.text = "菜鸟海澜"
,如果数值没有变化可以不用赋值,有变化一秒赋值一次
13. 避免使用Blocking Objects来遮挡射线,因为这是一个相当消耗性能的操作
14. Screen Space 和 World Space 中的Camera必须要指定,负责会每帧7-10次调用Object.FindObjectWithTag!!!
15. Layout这种东西少用,或者用了尽可能减少子节点的变动,(让结构简单点也行)因为会从变动节点递归向上调用GetComponents,而且要最大可能减少嵌套Layout。(不过没有开发时间还是用吧~~~)
16. Canvas下面的UI元素移动到屏幕外很远处,会分情况出现Drawcall数量变动的情况
- Screen Space -Camera模式下移除全部UI会引起Drawcall的变化
- Screen Space - Overlay模式下移除全部UI不会引起Drawcall的变化
- 但是这两种模式只移除部分UI(图片部分)并不会引起Drawcall的变化
-
而且在UI移动后会影响原来的Depth排序,造成合批失败产生更多的Drawcall
17. 频繁需要SetActive的物体可以使用Canva Group组件,可以有效降低重建消耗
18. 禁用Canvas组件本身可以避免重建消耗来达到隐藏的效果(前提节点没有改变),但是对应脚本上的OnEnable、OnDisable会触发,所以笔者一直用Canva Group组件
19. outline和shadow组件就不要用了,Text Mesh Pro性能更好,功能强大,还免费!!!
20. Frame Debug真是一个好工具,可以有效查看渲染顺序和不能合批的原因
21. 配合Profiler中新添加的UI性能监控真是锦上添花
22. Scroll Rect 组件对应的Content填加 Canvas 组件 ,因为对应的Mask 子元素依然参与全局的Depth排序,避免因拖动打乱原有的Depth排序,造成合批失败
23. 用户协议等巨型篇幅的文字显示,会造成Canvas.sendWillRenderCanvases 开销过大。因为内容过大,导致vertexhelper中的list的capacity过大,基本的clear操作都会非常耗时,所以用反射调用每个List的TrimExcess函数,如果反射不熟悉的同学请看Unity C#基础之 反射反射,程序员的快乐
下面为UGUI部分源码
24. 降低使用字体的种类。字体Font资源需要单独打包,否则会造成字体被重复打包到对应的UI Bundle里面。
25. Mask 与 Rect Mask 2D 的区别
建议按照实际需求进行权衡
-
Rect Mask 2D
- 节省 DrawCall 和 Overdraw
-
增加 Cull 开销(Canvas.SendWillRenderCanvases())
- 持续开销较低
- 拖动时开销较高
Mask
Rect Mask 2D