Unity UI模块优化(1.原理)

来源:互联网 发布:github mac客户端下载 编辑:程序博客网 时间:2024/06/11 23:38

参考链接:https://blog.uwa4d.com/archives/1875.html,详情请点击链接查看UWA的视频解析,尊重UWA版权。本文为个人看视频学习整理笔记,同视频有删减。

NGUI VS UGUI

一.元素更新方式

1.共同点:
NGUI:

public class UIGeometry{    public BetterList<Vector3> verts = new BetterList<Vector3>();    public BetterList<Vector2> uvs = new BetterList<Vector2>();    public BetterList<Color32> cols = new BetterList<Color32>();    public BetterList<Vector3> mRtpVerts = new BetterList<Vector32>();

这个类会临时的储存顶点信息,每个UI元素,不管是UISprite还是UILabel,都有一个对应的UIGeometry对象,有几个数组存储顶点信息,如位置、法线方向、颜色等。

UGUI:

public class VertexHelper : IDisposable{    private List<Vector3> m_Positions = ListPool<Vector3>.Get();    private List<Color32> m_Colors = ListPool<Color32>.Get();    private List<Vector2> m_Uv0S = ListPool<Vector2>.Get();    private List<Vector2> m_Uv1S = ListPool<Vector2>.Get();    private List<Vector3> m_Normals = ListPool<Vector3>.Get();    private List<Vector4> m_Tangents = ListPool<Vector4>.Get();    private List<int> m_Indices = ListPool<int>.Get();

每个UI元素都有个对应的VertexHelper对象,需要UI元素的位置、长宽等信息来填充这些数组。
(所以:这些数组里东西越多,填充的过程就越长)

对制作的影响:
1/ “动态”元素(经常会改变位置或缩放或颜色的)尽量少用Outline、Tiled Sprite;

2/ 尽量减少“动态”长文本(一个Label里文字太多)

注意:
以上三种不是说尽量少用,而是说使用时:
1/ 尽量减少他们在动态元素上的使用,或者使用时候尽量保证他们是静态的,即不太会改变它的颜色、缩放等。
2/ 尽量减少这些元素所在Canvas或者UIPanel的重建,英文他们重建时会涉及到这些元素的填充。

可见,NGUI和UGUI相同点:它会转化为数组,有一个填充的过程,所以说当我们的UI元素顶点数很多,那么填充的过程时间就会很长。

2.不同点:

1/ NGUI
UIPanel.LateUpdate:(每帧执行)
—轮询
—UIPanel.UpdateWidgets (在UIPanel.LateUpdate里每帧执行)

UpdateWidgets更新每一个激活状态的Widget的位置、状态等,有个更新和获取的过程,如果在更新过程中发现这个Widget发生了变化,那么会有一些其他的操作来引起一些开销;
即使UI们没有任何变化,轮询的开销还是会有的。所以NGUI里大的界面,就算是静态界面,也会有持续的开销。

2/ UGUI
Canvas.SendWillRenderCanvas
—队列
—m_LayoutRebuildQueue
—m_GraphicRebuildQueue
这两个队列分别记录那些layout和Graphic发生变化的元素,界面发生变化时,会在SendWillRenderCanvas回调里rebuild这两个队列里的元素。
没有轮询的过程,所以在UGUI里静态界面相当于0消耗。

小结:
所以大量静态UI元素放在一个地方,UGUI消耗小于NGUI。

对缓存机制的影响:

动态HUD的缓冲池,如血条、伤害跳字,这些会经常批量的出现,批量的消失,我们不会说出现就实例化,消失就destroy,所以我们需要用缓存。一般我们可能会首先想到用SetActive,而UI元素这样会有额外的开销,所以我们要深入考虑。

NGUI:

缓冲池元素适量:Color.a=0,移除 (NGUI中Scale设为0仅仅把网格scale为0,但是顶点数还在,drawcall还会提交;alaph设为0则会把顶点都去掉)
缓存池元素多:SetActive(false)
Timer +二级缓存(退出战斗后,逐渐把缓冲池里color.a=0的缓存按批禁用,于是出了战斗后缓冲池里UI不会有持续的开销)

UGUI:

Scale = 0,Alpha Group = 0快速隐藏UI,且不会有顶点重建,不会触发激活和经验的额外开销;
在UGUI不要用Color.a=0,这个在UGUI仅仅将alaph设为0,在drawcall上是没有任何变化的,相当于贴了个透明面片,还是会画到场景里。


二.DrawCall合并规则

1.渲染顺序
NGUI:depth
手动设置depth值,然后以UIPanel为单位,根据depth的大小做一个排序,然后相同材质的进行合并。

UGUI:hierarchy
—重叠检测
—分层合并

如右图:不同颜色为不同图集,数字为drawcall。

2.调试工具
—NGUI:DrawCall Tool
—UGUI:Frame Debugger

3.对界面制作的影响

—UGUI
不规则图标的摆放(实际重叠了,UGUI这里DrawCall没有办法合并)
UI元素的旋转(旋转后,如图实际上两个元素重叠了)
动态遮挡
3D UI(3D UI旋转后会发生重叠,因为是先投影到2D上)

—NGUI
手动排序


三.网格更新机制

NGUI:
UIPanel.LateUpdate 两种更新方式
-UIPanel.FillDrawCall 更新单个DrawCall
-UIPanel.FillAllDrawCalls 更新所有DrawCall

UGUI:
Canvas.BuildBatch 更新所有DrawCall
-WaitingForJob(5.2之后)
-PutGeometryJobFence(5.2之后)
-BatchRenderer.Flush*(开了多线程渲染则前两个会消失)

执行上:
如上血条+文本:
NGUI里合成后是两个mesh,会根据不同的drawcall拆分不同的网格;
在UGUI里合成后是一个mesh,2个submesh,UGUI里合并网格时,以canvas为单位,一个Canvas下所有元素会合在一个网格里,只是会分不同submesh。所以一个几何很复杂的Canvas,更新下面任何一个几何元素时,都会涉及到一个很大的dpu的修改。

对界面制作的影响
UGUI:
拆分Canvas(动静分离)

NGUI:
控制FillAllDrawCalls
拆分UIPanel


综上: (>表示更有优势,消耗更低)

功能界面的DrawCall控制 NGUI>UGUI
功能界面的网格更新控制 NGUI>UGUI
动态HUD界面的网格更新控制 NGUI << UGUI
堆内存控制 NGUI << UGUI

原创粉丝点击