博客
关于我
(五)UGUI源码分析之Rebuild(布局重建、图形重绘)
阅读量:508 次
发布时间:2019-03-07

本文共 2255 字,大约阅读时间需要 7 分钟。

CanvasUpdateRegistry 和 ICanvasElement 相关 Rebuild 操作 时机

最近在优化 UI 组件性能时,深入研究了 CanvasUpdateRegistry、ICanvasElement、LayoutGroup 等相关组件的工作原理,尤其是 Rebuild 操作的实现细节。通过阅读源码和调试实例,整理出以下关键信息,供开发者参考。


一、添加 需要 Rebuild 的 元素 时机

1. 自身 继承 ICanvasElement 的 类

ICanvasElement 接口的继承类(如 ScrollRect、Toggle、Slider 等)在以下时机添加布局元素:

  • ScrollRect

    • OnEnable 方法
    • SetDirtyCaching 方法(触发时赋值 viewport、horizontalScrollbar、verticalScrollbar 等属性时)
    • OnDisable 方法,会移除元素,并调用 LayoutRebuilder.MarkLayoutForRebuild(rectTransform)
    • OnRectTransformDimensionsChange(RectTransform尺寸变化时)
    • horizontalScrollbarVisibility、verticalScrollbarVisibility 修改时
  • Toggle

    • 编辑模式下,在PrefabUtility.IsPartOfPrefabAsset(this) 为 false 且未运行游戏时,调用 OnValidate 方法进行添加布局元素。
  • Slider

    • 同样在编辑模式下,调用 OnValidate 方法进行添加布局元素。

2. 非继承 ICanvasElement 的 类

对于不直接继承 ICanvasElement 的组件,需要通过 LayoutRebuilder.MarkLayoutForRebuild(rectTransform) 方法将父物体中拥有 LayoutGroup 组件的物体封装到布局列表中。具体规则如下:

  • 如果当前物体有 LayoutGroup 且父物体无,则将当前物体添加到布局列表。
  • 如果父物体有 LayoutGroup 而当前物体无,则将父物体添加到布局列表。
  • 如果当前物体和父物体均无 LayoutGroup,则不添加。

二、各大类的 Rebuild 方法 具体 内容

1. 只参与布局(布局前、布局后)

  • ScrollRect

    • 具体操作通过自身的 Rebuild 方法(继承自 ICanvasElement)。
    • 在编辑模式下,Toggle 和 Slider 会调用 onValueChange 方法(布局前)。
    • 借助 LayoutRebuilder 进行计算,确定水平和垂直布局容器的合适尺寸,然后确定子物体的尺寸和位置。
  • LayoutRebuilder

    • 在布局过程中,通过 Rebuild 方法计算 Horizontal 和 Vertical 布局容器的正确大小,并更新子物体的尺寸和位置。
  • 其他布局相关类(如 HorizontalLayout、VerticalLayout、GridLayout):

    • 在 Rebuild 方法中,根据容器大小参数计算子物体布局信息,完成布局更新。

2. 只参与绘制(绘制前、绘制后)

  • Graphic 类及其子类(如 Text、Image 等):

    • 在绘制前,通过 SetVerticesDirty(V)、SetMaterialDirty(M)、OnCullingChanged(C)等方法标记为需要更新。
    • 其他触发绘制列表更新的时机包括:
      • Text 类:设置 text、supportRichText、resizeTextForBestFit 等属性时。
      • Image 类:设置 type、preserveAspect、fillCenter 等属性时,或在 OnCanvasHierarchyChanged 方法。
      • Shadow/Outline:设置 useGraphicAlpha、effectDistance、effectColor 等属性时。
  • RawImage、BaseMeshEffect、AspectRatioFitter 等

    • 在属性改变时调用 V 方法(如 texture 改变、uvRect 改变)。
    • 或在 RectTransform 属性变化时触发(如 OnRectTransformDimensionsChange)。

三、其他注意事项

  • _prefabInstanceUpdated 事件:
    • 在 PrefabUtility namespace注册了 OnPrefabInstanceUpdates 方法。
    • 当预制体实例化后,会调用 LayoutRebuilder.MarkLayoutForRebuild(rectTransform)。
    • 主要用于更新场景中的 LayoutGroup 组件。

四、总结

通过以上分析,可以清晰地知道哪些组件在何时触发 LayoutRebuild 和 GraphicRebuild 操作。理解 Rebuild 的触发时机,对于优化 UI 更新效率至关重要。建议在实际开发中,结合项目需求,对相关组件的 Rebuild 行为做细致调试和优化。

如有疑问或需要更深入的实现细节,可以参考 UnityEditor.UI namespace 中的相关类实现。

转载地址:http://teucz.baihongyu.com/

你可能感兴趣的文章
OS2ATC2017:阿里研究员林昊畅谈操作系统创新与挑战
查看>>
OSCACHE介绍
查看>>
SQL--合计函数(Aggregate functions):avg,count,first,last,max,min,sum
查看>>
OSChina 周五乱弹 ——吹牛扯淡的耽误你们学习进步了
查看>>
SQL--mysql索引
查看>>
OSChina 周四乱弹 ——程序员为啥要买苹果手机啊?
查看>>
OSChina 技术周刊第十期,每周技术抢先看!
查看>>
OSError: no library called “cairo-2“ was foundno library called “cairo“ was foundno library called
查看>>
Osgi环境配置
查看>>
OSG中找到特定节点的方法(转)
查看>>
OSG学习:C#调用非托管C++方法——C++/CLI
查看>>
OSG学习:几何体的操作(二)——交互事件、Delaunay三角网绘制
查看>>
OSG学习:几何对象的绘制(三)——几何元素的存储和几何体的绘制方法
查看>>
OSG学习:几何对象的绘制(二)——简易房屋
查看>>
OSG学习:几何对象的绘制(四)——几何体的更新回调:旋转的线
查看>>
OSG学习:场景图形管理(一)——视图与相机
查看>>
OSG学习:场景图形管理(三)——多视图相机渲染
查看>>
OSG学习:场景图形管理(二)——单窗口多相机渲染
查看>>
OSG学习:场景图形管理(四)——多视图多窗口渲染
查看>>
OSG学习:新建C++/CLI工程并读取模型(C++/CLI)——根据OSG官方示例代码初步理解其方法
查看>>