UI输入
Q1:关于UI的Mask遮挡特效,能否提供一些解决思路呢?
目前由于UI与粒子系统是两个相对独立的模块,因此两者的Mask遮挡并没有简单直接的方法。我们建议从以下几种方式来考虑实现:
- 将粒子系统转为序列帧,通过纯UI的方式来实现;
- 通过RenderTexture,添加一个相机来实现方形的“裁剪”;
- 参考UI的内置Shader,编写一个受Stencil Buffer影响的Shader,同时通过给粒子系统以及UI的SortingLayer,OrderInLayer设置适当的值,从而实现Mask组件对粒子系统的遮罩。
UI输入
Q2:请问,Canvas里的东西移出了屏幕后,DrawCall没降低,那么它还会每帧去绘制吗?
DrawCall没降低,说明CPU依然将这部分的网格提交到了GPU。因此虽然UI元素已经不可见,但其CPU开销(包括切换渲染状态,提交VBO等)依然是在的,只是对GPU不会造成明显影响,因为最终并没有进行像素的渲染。
UI 输入
Q3: 多人同屏的时候,人物移动会使得头顶上的名字Mesh重组,从而导致较为严重的卡顿,请问一下是否有优化的办法?
A: 如果是用UGUI开发的,当头顶文字数量较多时,确实很容易引起性能问题,可以考虑从以下几点入手进行优化:
-
尽可能避免使用UI/Effect,特别是Outline,会使得文本的Mesh增加4倍,导致UI重建开销明显增大;
-
拆分Canvas,将屏幕中所有的头顶文字进行分组,放在不同的Canvas下,一方面可以降低更新的频率(如果分组中没有文字移动,该组就不会重建),另一方面可以减小重建时涉及到的Mesh大小(重建是以Canvas为单位进行的);
-
降低移动中的文字的更新频率,可以考虑在文字移动的距离超过一个阈值时才真正进行位移,从而可以从概率上降低Canvas更新的频率。
UI 输入
Q4:Unity自带的UI Shader处理颜色时,改 _Color属性不会触发顶点重建吗?
在UI的默认Shader中存在一个Tint Color的变量,正常情况下,该值为常数(1,1,1),且并不会被修改。如果是用脚本访问Image的Material,并修改其上的Tint Color属性时,对UI元素产生的网格信息并没有影响,因此就不会引起网格的Rebuild。但这样做因为修改了材质,所以会增加一个Draw Call。
UI 输入
Q5:UGUI的SrcollView Mask遮挡不住特效,这个有没有可行的解决方案?
UGUI的Scrollview Mask组件使用的是Stencil Buffer,需要严格确保渲染顺序的正确性,这对于粒子系统或是其他的模型较难控制,因此可以尝试通过其他的方式,如实现一个四边形Alpha 裁剪的Shader,将ScrollView的裁剪区域传入Shader,从而模拟一个特效被“遮罩”的效果。以下是宣雨松博客中提出的一种方式,可以作为参考:
http://www.xuanyusong.com/archives/3518
UI 输入
Q6:我发现当把UI挪到屏幕外时,Draw Call不会减少,只有设置Enabled去掉才能减少。UI是没有遮罩剔除这类功能吗? 那是否意味着ScrollRect只能自己做动态加载或者动态设置Enabled之类的优化了?
因为UGUI合并网格时是以Canvas为单位的,所以只把一部分UI元素移除屏幕并不能降低Draw Call,在Unity 5.2版本以前需要满足两点:
1. 使用Screen Space – Camera 的 Render Mode;
2. 需要将移出的UI元素放在独立的Canvas中,然后整体移出屏幕。但在Unity 5.2版本之后,上述方法也已经失效。
因此我们建议,在移出后,通过将Canvas的Layer修改为相机Culling Mask中未选中的Layer来去除这部分多余的Draw Call,> 但这种方法同样需要将移出的UI元素放在独立的Canvas中。这种方法,相比Enabled的设置,可以减少一定的CPU开销。而对于ScrollRect,如果包含的UI元素较多,确实需要自己做动态加载和动态设置Enabled来进行优化。
UI 输入
Q7:UI展示动画时,使用Mask做和使用UI本身做 ,哪个效率会更高些?
一般来说建议尽可能少用Mask组件,该组件的使用对于Draw Call会有较大的影响,也可尝试用 Rect2D Mask来代替。而如果直接通过改变UI元素本身来做动画,当涉及的UI元素数量较大时,容易引起较高的网格重建开销。
UI 输入
Q8:关于UI开发,NGUI和UGUI究竟哪个性能更好呢?
从理论上来说,没有什么依据可以证明UGUI的性能一定比NGUI更优异。在UWA的测评报告中,对于NGUI来说,主要统计UIPanel.LateUpdate\UICamera.Update\UIRect.Update和UIRect.Start;对于UGUI来说,主要统计Canvas.BuildBatch和Canvas.SendwillRenderCanvases。相对于NGUI来看,UGUI确实在以下方面存在提升性能的可能:首先,在Unity 5.x 版本中,Unity逐渐将一部分UGUI的计算放到子线程去做,以此来缓解主线程的压力;其次,UGUI的UIMesh重建是通过底层C++代码实现的,而NGUI只能通过在上层不断创建vertex list来进行,这样在堆内存的管理上,UGUI确实要好很多,带来的隐性收益就是GC触发次数会少很多。但不能表示NGUI做出来的UI性能就一定比UGUI差,这个说法是不存在的。而且,在我们深度优化的过程中发现,NGUI同样可以达到很高的性能水准。所以,NGUI和UGUI都是很好的工具,只要把它们的特性掌握好,都可以做成性能很棒的UI界面。
UI 输入
Q9: 在UWA上周六的分享会中,我收获了不少性能优化的知识点,同时也有个疑惑,是关于“UI Mesh重构”这个话题。当时UWA说“把一个UI界面移出屏幕或者缩放是不会引起UI Mesh的重构”,但是我今天测试了一下,在UISprite上面挂了一个脚本,让它移出相机屏幕或者手动更改坐标时,发现都会出现CPU峰值,看上去确实是Mesh重建造成的。下面是我的测试截图:
上图是NGUI的第一个Scene,里面就在父节点只有一个UIPanel,这是我的测试环境。
上面两张图是我的测试截图,主要包括移动Transform和缩放Transform数据等,从Profiler中看都有Mesh重建。因此,我的测试结论是:无论是移出屏幕还是缩放为0,以及Deactivate操作都会引起Mesh的重构。希望UWA可以再测试一下,给一个结论。
改变UI Transform(移出屏幕、Scale为0等)是需要以Panel为单位的,即不要移出单个Widget,而是将不再使用的UI界面(Panel)整体移出屏幕外。该朋友提供的测试例子没有问题,因为只用了一个UIPanel,且移动的是其中的Widget,所以造成了这个UIPanel的整体耗时。因此,建议尝试把需要移除的UI元素放在一个独立的UIPanel中,然后直接移动UIPanel,这样就不会有CPU峰值出现了。
关于隐藏UI的详细描述,可以参考我们之前的技术推送:NGUI性能优化技巧。下文是部分片段:
其中,值得研发团队注意就是第二点中的“以UIPanel为单位”,因为Mesh的拼合是以UIPanel为单位的,整体移动UIPanel不会重建或更新Mesh,但移动其中一部分元素则依然会更新Mesh的。
UI 输入
Q10:对于UGUI文字花屏问题,有什么推荐的解决方法吗?
对于UGUI字体花屏的现象, 很有可能是字体的UV不准确导致。对此,我们推荐两篇博文,大家可以通过其中的具体做法来进行解决。
关于UGUI字体花屏和乱码:http://www.cnblogs.com/yaukey/p/unity_ugui_font_texture_uv_wrong.html
UGUI研究院之Text字体花屏(二十二):http://www.xuanyusong.com/archives/4259