博客
关于我
(五)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/

你可能感兴趣的文章
python3处理json文件中含有中文dumps的应用
查看>>
Python3子进程输出
查看>>
Python3学习笔记3,变量、运算符
查看>>
Python3学习笔记(urllib模块的使用)
查看>>
python3安装scapy_Linux下安装scapy-python3
查看>>
python3实现socket通信
查看>>
Python关于numpy.transpose函数详细解析附代码
查看>>
Python3导入自定义模块的3种方式
查看>>
python3打开txt文件_使用Python 3从文本文件读取句子并添加到列表中
查看>>
python3爬虫抓取智联招聘职位信息代码
查看>>
Python3爬虫数据入数据库---把爬取到的数据存到数据库,带数据库去重功能
查看>>
python3的 pymysql把mysqldb库取代了,让python 3支持mysqldb的解决方法
查看>>
Python3笔记——IDE的选择
查看>>
python3简单使用requests 用户代理,cookie池
查看>>
Python3组播通信编程实现教程(发送者+接收者)
查看>>
Python3编写网络爬虫10-数据存储方式三-CSV文件存储
查看>>
python3读取redis返回数据带有'b'的问题
查看>>
Python3连接MySQL
查看>>
Python关于isinstance函数的解析 | 附Demo(全)
查看>>
Python3:setup.py:完成所有任务的PIP安装(Build_ext+Install)
查看>>