NGUI 什么时候用UIPanel

2015年01月30日 13:08 0 点赞 0 评论 更新于 2025-11-21 15:15

在探讨 NGUI 中何时使用 UIPanel 之前,我们先通过一个形象的比喻来理解相关概念。在这个比喻里,UIGeometry 如同为烹饪准备食材,它负责收集和组织 UI 元素的几何数据;UIDrawCall 就像是煮菜的工具,例如锅、炉子等,它的作用是将这些几何数据渲染到屏幕上;UIPanel 则相当于大厨,掌控着何时进行渲染操作,也就是决定何时该“煮菜”;而 UIWidget(包括 UILabel、UISprite 和 UITexture 等)则是这道菜最终的呈现方式,代表着 UI 元素在屏幕上的具体外观。

接下来,我们详细讲解 UIPanel 的工作流程。更新 UIDrawCall 是 UIPanel 最重要的工作之一。在更新 UIDrawCall 时,还需要对 UIPanel 的其他信息,如 transform、layer、widget 等进行更新。以下是 UIPanel 的 LateUpdate() 函数代码及详细解释:

/// <summary>
/// Main update function
/// </summary>
void LateUpdate ()
{
// Only the very first panel should be doing the update logic
if (list[0] != this) return;

// Update all panels
for (int i = 0; i < list.size; ++i)
{
UIPanel panel = list[i];
panel.mUpdateTime = RealTime.time;
panel.UpdateTransformMatrix();
panel.UpdateLayers();
panel.UpdateWidgets();
}

// Fill the draw calls for all of the changed materials
if (mFullRebuild)
{
UIWidget.list.Sort(UIWidget.CompareFunc);
Fill();
}
else
{
for (int i = 0; i < UIDrawCall.list.size; )
{
UIDrawCall dc = UIDrawCall.list[i];
if (dc.isDirty)
{
if (!Fill(dc))
{
DestroyDrawCall(dc, i);
continue;
}
}
++i;
}
}

// Update the clipping rects
for (int i = 0; i < list.size; ++i)
{
UIPanel panel = list[i];
panel.UpdateDrawcalls();
}

mFullRebuild = false;
}

代码解释:

  1. 逻辑执行条件
    • if (list[0] != this) return;:只有列表中的第一个 UIPanel 会执行后续的更新逻辑,避免重复更新。
  2. 更新所有面板信息
    • 通过 for 循环遍历所有 UIPanel,依次更新每个面板的时间、变换矩阵、图层和小部件信息。
  3. 填充绘制调用
    • 如果 mFullRebuildtrue,则对所有 UIWidget 进行排序,并调用 Fill() 函数填充所有绘制调用。
    • 如果 mFullRebuildfalse,则遍历 UIDrawCall 列表,对于标记为 isDirty 的绘制调用,尝试填充它。如果填充失败,则销毁该绘制调用。
  4. 更新裁剪矩形
    • 再次遍历所有 UIPanel,调用 UpdateDrawcalls() 函数更新裁剪矩形。
  5. 重置标志
    • mFullRebuild 标志重置为 false

为了更直观地展示 LateUpdate() 函数的调用栈,这里贴出一张手绘的调用栈图(虽然画图水平有限,但也是经过一番琢磨才完成的)。

通过以上内容,我们对 UIPanel 的工作原理有了更深入的了解。那么在实际使用中,什么时候应该使用 UIPanel 呢?一般来说,当你需要对一组 UI 元素进行统一管理,例如统一控制它们的渲染顺序、裁剪区域、图层等时,就可以考虑使用 UIPanel。它能够帮助你更高效地管理和优化 UI 渲染。

作者信息

feifeila

feifeila

共发布了 3994 篇文章