UGUI技术之UI的深入学习分析

2015年03月19日 10:42 0 点赞 0 评论 更新于 2025-11-21 13:30

今天抽空深入研究了一下UGUI的深度机制。不得不说,UGUI在处理UI深度方面表现十分出色。在以往使用NGUI时,UI的深度是通过指定一个数值来确定的,数值越大,该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 () {
// 实例化一个名为 "button" 的 GameObject
GameObject button = GameObject.Instantiate(Resources.Load<GameObject>("button")) as GameObject;
// 设置 button 的父节点为当前对象
button.transform.parent = transform;
// 设置 button 的本地位置为原点
button.transform.localPosition = Vector3.zero;
// 设置 button 的本地缩放为单位向量
button.transform.localScale = Vector3.one;

// 查找名为 "A" 的 GameObject
GameObject AObj = transform.Find("A").gameObject;
// 查找名为 "B" 的 GameObject
GameObject BObj = transform.Find("B").gameObject;

// 将 button 的兄弟节点索引设置为 AObj 的兄弟节点索引
button.transform.SetSiblingIndex(AObj.transform.GetSiblingIndex());
}
}

在上述脚本中,transform.SetSiblingIndexGetSiblingIndex 方法分别用于设置和获取GameObject在兄弟节点中的位置。通过合理使用这两个方法,我们可以在运行时动态调整UI元素的显示顺序。

作者信息

menghao

menghao

共发布了 3994 篇文章