Unity3D种UGUI与NGUI的对比差别(2)

 
  

层级管理概念

UGUI采用Hierarchy排序的方式,替代了NGUI中的Depth排序。 更精准的说,NGUI的排序是通过Depth、Z值、RenderQueue共同影响的,整体规则过于复杂;而UGUI采用的排序比较简单,在Canvas内部元素采用Hierarchy方式排序,在Canvas同级之间通过Sort Order或者是Hierarchy来进行排序;UI的组织方式,就是层级的可见顺序,跟平常的认知具有一致性。

3DMesh嵌套问题

通常UI开发中都会存在UI与Unity3DMesh嵌套的需求,特别常见的是角色与粒子特效。通常有两种方案来处理嵌套。第一种方案是将3DMesh渲染到一张RenderTexture中,再用这张RenderTexture来与其他的UI做排序。这种方案在UGUI与NGUI中都可用,比较适合角色这种渲染目标唯一并使用控件唯一的需求。 另一种方案是将3DMesh的渲染与UI一起排序,UGUI跟NGUI都没有提供将Unity3DMesh内嵌为一个UI元素进行排序的功能。 在NGUI中,官方论坛推荐使用一个脚本来动态修改Mesh的RenderQueue,达到跟UI排序的目的。具体逻辑是每帧获取目标UI的RenderQueue,同步更改Mesh的RenderQueue。因为NGUI默认的排序方式,是每个drawcall对应一个3000以上的RenderQueue。 在UGUI中,采用的是Sorting Order的方式来做排序,需要修改的是粒子Renderer的Sorting Order来跟UI进行排序。所以使用Sorting Order来管理canvas之间的层级关系时,需要留出足够的Order厚度来支持Canvas内部元素嵌套使用粒子特效。

Mask裁剪

NGUI中的Mask裁剪,是通过透明度裁剪实现的;UGUI中的Mask裁剪,是通过Stancil裁剪实现的。透明度裁剪,需要在shader中做额外的透明度因子计算,并且被裁剪掉的像素(透明度为0的像素)还是会参与到后续的Blending等渲染流程;Stancil裁剪,需要额外一个pass来渲染mask区域,但没通过Stencil的像素会被丢弃,不参与后续渲染流程。权衡下来,UGUI的做法会更省一点。特别是被裁剪区域特别大,或者区域内重叠框体特别多的情况。

3DMesh裁剪

在UI的mask组件内部层级嵌套使用3DMesh时,粒子也需要被裁剪。NGUI与UGUI都需要对嵌套的3DMesh做裁剪处理。

图集管理模式

UGUI不再使用自定义Atlas资源,image中使用的是Sprite,图集可以用Unity提供的Sprite Picker来合成。 NGUI抛弃了Unity的Sprite组件,自定义了一套图集资源及管理模式(Atlas),提供合图工具、Sprite选取窗口、并提供了对单个资源做静态深加工(加阴影、轮廓)的功能。
UGUI整合了Unity的Sprite,使用Sprite Picker来做合图集,功能上简化了许多,但可以直接从Unity的Project窗口中直接把Sprite或者Multiple sprite中的某个Sprite直接拖到Image中,操作上简化了些。 对于小型游戏UI来说,UGUI的简化版功能会更便捷些。但是对于MMORPG这种有复杂UI层级的游戏来说,使用UGUI的自动合图集,由于可控度太低,大概率会造成内存浪费,或者Drawcall Issue。所以,复杂UI层级的游戏,使用NGUI的图集管理模式,可控度会更高些。在UGUI中,可以通过使用第三方工具(如TexturePicker)合图后转成Multiple Sprite来达到跟NGUI相似的可控度。 采用Multiple Sprite有个缺点,不能直接动态加载这个MultipleSprite中包含的某个Sprite,需要使用LoadAll接口将该图集所有的Sprite都加载以后,再遍历对比出所需的Sprite。而Unity的LoadAll函数,是会对Resource中所有文件进行遍历的。当Resource中的文件数量非常庞大的时候,遍历耗时会造成性能卡顿。 这个问题,可以通过将自定义Altas中的Sprite导出成Prefab,并提供一个Sprite Prefab的加载缓存管理器即可。除此之外,精简Resource中的文件数量也是一种很好的方案。“Best Practices for the Resources System —— Don't use it”。[2]

渲染性能

Batch算法

NGUI的Panel内部排序:在Widget新增时,是通过Insert到List中进行排序的,整个算法的时间复杂度是O(n),元素越多,效率越差。在Rebuild时,直接遍历WidgetList,按材质、贴图、shader来拆drawcall,进行batch。 UGUI的canvas内部排序:由于没有明确的指定次序,UGUI需要按照顺序,对每个UI控件遍历出相交情况,再查看是否可以合批,算法比NGUI更复杂些(判断相交的算法有优化,时间复杂度小于O(n2))。

Native Code 优势

然而,NGUI实质上是创建自定义Mesh,使用Mesh Renderer来做渲染的。对UI的合批操作逻辑在C#层。UGUI定义了Canvas组件,使用Canvas Renderer来做渲染,在C++层做合批逻辑,所以UGUI处理动态层的性能会比NGUI更佳。 对于有频繁动画需求的UI,使用UGUI会比使用NGUI有性能优势。

EventSystem & Raycasters

UGUI中采用Event&Raycasters的设计,来替代NGUI中的Collider&sendMessage。 在NGUI中,默认控件是不参与交互的,除非加上Collider;而在UGUI中,默认控件是参与交互的,除非使用canvas Group组件来禁止交互(在5.x版本中,可以通过去掉勾选raycast Target来禁止)。所以在使用UGUI的过程中,突然发现某个点击无效了,可以优先考虑是否是最近有人添加新的Text把消息遮挡了。 NGUI的交互事件是通过SendMessage来发送消息的,SendMessage的性能比较差,Delegate与SendMessage的性能测算,前者会快10倍左右[3]。UGUI的交互事件改为通过事件回调机制来发送消息,对于交互输入这种比较频繁调用的消息来说,性能上提升不少,比较直接反馈是scroll view的滑动流畅度。

Layout布局

UGUI的布局,采用Layout组件群(Layout Element、GridLayoutGroup、Content Size Fitter等),来替代NGUI中的Table跟Grid。 对于UGUI来说,Layout是比较费的组件,因为每次被标记Dirty时,它需要重算所有的子元素的大小跟位置。一般来说,只用在跟内容的相对大小相对位置有关联的复杂布局中。例如说scrollview中动态添加新Item或者是文本背景纹理需要根据文本的长宽动态变化的时候[4]。 平时可以在编辑模式下,用Layout组件来辅助界面快速布局。另外比较小规模的相对布局(如2*2table),可以使用RectTransform的Anchor替代。因为RectTransform的计算是在C++层发生的,比同等的Layout更效率

UI动画

NGUI整合了ITween,并将ITween的使用封装成脚本,可以非常方便制作出各种旋转、平移、缩放的效果,易用性很强。 UGUI官方文档建议是采用Unity的Animation System来制作UI动画[5],但是使用Animation动画有个比较明显的缺陷,在UI频繁显隐的时候(Active/Inactive),Animator会重新Rebind一次Controller,导致无意义的性能损耗,所以UGUI的动画实现,可以有另一个option,通过整合DoTween来实现。Dotween不存在Animation的反复初始化问题,并且它使用了一些缓存策略,相对于ITween来说,每帧耗时更短,效率更高,产生GC更少。[6]

总结

从易用性角度来看,NGUI比UGUI好用一点点

NGUI的工具支持度更高: Drawcall Tool,可以查看UI的Drawcall分布以及哪些元素影响了Drawcall分布,可以很方便的调整顺序优化Drawcall; Prefab Toolbar,可以将Prefab模板直接保存成可视态,通过拖曳到Hierarchy创建新组合; Editor Right - Click Menu, 在编辑场景中,右键弹出的操作菜单,可以在多重叠控件中,拾取某一个,或者对某个控件进行层级操作。在开发多层级复杂UI的时候,这个功能是可以提升效率的。 ITween, NGUI整合了ITween并提供了封装后的使用脚本,可以很方便快捷的完成UI的动画需求,如旋转、缩放、变色、移动等。 UGUI的概念封装更好,可视化更高: 将层级管理改为Hierarchy排序以后,比较符合人类认知; 对于可交互空间的navigation顺序,可以直接给出可视图; 深度利用Unity的内核,如Inspector,Sprite等;

从可扩展性来看,UGUI略逊NGUI一点点

UGUI与NGUI都可以通过简单组件组合,来满足大多数的需求;也可以通过继承扩展现有组件来满足特殊需求; NGUI更极端一点,可以通过直接修改源码来满足需求。UGUI虽然也开放了源码,但只是C#部分,C++部分是无法做改动的。

从性能来看,UGUI比NGUI有底层优势

UGUI的排序及合批逻辑都在C++层处理,效率更高; 采用EventSystem的分发模式,效率更高;

结论

除以上总结外,UGUI还有几个优势:全免费、官方身份、跟Unity可深度融合(多线程)等。 选用UGUI应该是趋势,因为性能是关键, 易用性可以通过开发辅助工具或者扩展组件来弥补。随着使用者越来越多,UGUI会越来越强大。

Reference

[1]   Unity Manual - UI - Base Layout [2]   Best Practices -- The Resources folder [3]   Unity3D的Delegate和SendMessage的性能差测试 [4]   UGUI中实现底图自适应size的方法 [5]   Unity Manual - UI - Animation Integration [6]   Unity CPU占用-DoTween与iTween效率对比

查看原文: http://www.51xyyx.com/3055.html

你可能感兴趣的:(Unity3D种UGUI与NGUI的对比差别(2))