最新文章
泰课在线 | 微信拼团成功后如何获取课程?
08-09 17:57
Unity教程 | 使用ARKit为iOS开发AR应用
07-31 17:23
Unity Pro专业版7折订阅四选一工具包之VR开发与艺术设计
07-28 11:47
网友使用虚幻UE4实现CAVE 多通道立体渲染的沉浸式环境
07-27 11:57
VR晕动症调查:未来5年内大部分VR晕动症将得到解决
07-27 11:26
AMD CEO:未来3-5年最重要 希望5年达1亿VR用户
07-27 10:44
关于uGUI与2D角色的显示层级
接触Unity3D已有一段时间,项目组在UI解决方案的选型上一直采用原生的uGUI,因此我也使用了一段时间的uGUI,并在其使用方面积累了一些经验。
一、uGUI的基本特性
游戏中的UI与其他游戏元素本质上并无太大差异,不同之处在于,UI通常由2D图片组合而成,包含较多透明元素与渐变元素,且一般显示在屏幕的最顶层。
在使用NGUI时,UI的深度是一个指定的数值,数值越大越靠前。在布置复杂界面时,常常会不知道该如何填写深度值,这让人十分困扰。而使用uGUI则可轻松解决这一问题。例如,在场景中若B图片显示在A图片前面,查看Hierarchy视图会发现,由于A在B的上面,所以Unity会优先渲染A,然后再渲染B,从而使得B显示在A的上面。若想让A图显示在B图的上面,只需在Hierarchy视图里将B拖拽到A的上面即可。
如果一个GameObject下面有多个精灵,其渲染顺序遵循以下规则:首先看父节点在Hierarchy视图中的排序,以此决定父节点的渲染先后;然后依次查看子节点在Hierarchy视图中的排序;若还有孙节点,以此类推。在没有ABA叠层的情况下,图集始终只会产生一个drawcall。因此,在布置界面时,精心设计节点顺序可以节省大量的drawcall。
二、渲染绘制顺序示例分析
下面通过具体示例深入分析渲染绘制顺序。假设UIMain和UINext是同级目录,由于UINext在UIMain下面,所以Unity会优先渲染UIMain,进而UINext将显示在屏幕最前面,UISub的原理与此相同。由此可得出精灵从前面到后面的显示排序为:NextB > NextA > SubB > SubA > MainA > MainB。
在布置界面时,我们可以依据这个排序规则来最小化drawCall。但如果需要在运行时在两个图之间插入一个图,该如何实现呢?以下是示例脚本:
using UnityEngine;
using System.Collections;
public class UIMain : MonoBehaviour
{
void Start()
{
GameObject button = GameObject.Instantiate(Resources.Load<GameObject>("button")) as GameObject;
button.transform.parent = transform;
button.transform.localPosition = Vector3.zero;
button.transform.localScale = Vector3.one;
GameObject AObj = transform.Find("A").gameObject;
GameObject BObj = transform.Find("B").gameObject;
button.transform.SetSiblingIndex(AObj.transform.GetSiblingIndex());
}
}
在上述脚本中,transform.SetSiblingIndex 和 GetSiblingIndex 方法用于设置和获取GameObject在兄弟节点中的位置。
三、uGUI性能优化的最佳实践
uGUI的性能涉及多个方面,以下是一些经过整理的最佳实践建议:
- 图集设计
- 重用图集:设计UI时要考虑重用性,像一些边框、按钮等可作为共享资源,放置在1 - 3张大图集中,称为重用图集。
- 功能图集:将其它非重用UI按照功能模块进行划分,每个模块使用1 - 2张图集,即功能图集。
- 图集合并:对于一些同时用到功能图集与重用图集的UI,若功能图集剩下的“空位”较多,可考虑将重用图集中用到的元素单独提取出来,合并到功能图集中,使UI仅依赖于功能图集,通过一定的冗余来提升性能。
- Drawcall优化
- Batch处理:具有相同材质和纹理的UI元素可以进行Batch处理,可Batch的UI上下叠放不会影响性能,但不能Batch的UI元素叠放会增加Drawcall开销。
- 层叠关系检查:要留意UI元素间的层叠关系,建议使用“T”工具查看其矩形大小。因为有些图片虽然透明,但叠放在其他UI上面且无法Batch时,会无故增加许多Drawcall。
- 组件层叠优化:UI中常见的Image与Text组件,当Text叠放在Image上面(如Button),且Text上又叠放了一个图片时,至少会多产生2个Drawcall,此时可考虑将字体直接印在下面的图片上。
- 层级调整:某些情况下,可人为增加层级以减少Drawcall。例如,一个Text的层级为0,另一个可Batch的Text叠放在图片A上,层级为1,此时两个Text因层级不同会产生2个Drawcall。若在第一个Text下方放置一个透明的图片(与图片A可Batch),两个Text的层级就会一致,Drawcall可减少一个。
- Mask使用注意事项
- 避免使用Mask:应尽量避免使用Mask,因为Mask的功能有时可通过变通方式实现,比如设计一个边框,将其叠放在最上面,当底下的UI移动时,就会被边框遮住。
- 评估性能损耗:若必须使用Mask,需评估其带来的性能损耗,并尽量将其降至最低。例如,当Mask内的UI是动态生成的(如List组件),要留意生成的UI之间是否存在重叠现象。
此外,有空可以多到“泰斗社区”学习交流。由于个人能力有限,文中可能存在一些纰漏,欢迎大家指正。