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

你可能感兴趣的文章
postgres10配置huge_pages
查看>>
PostgreSQL 10.0 preview sharding增强 - pushdown 增强
查看>>
PostgreSQL 10.0 preview 变化 - pg_xlog,pg_clog,pg_log目录更名为pg_wal,pg_xact,log
查看>>
PostgreSQL 10.1 手册_部分 II. SQL 语言_第 15章 并行查询_15.2. 何时会用到并行查询?...
查看>>
PostgreSQL 10.1 手册_部分 II. SQL 语言_第 9 章 函数和操作符_9.23. 行和数组比较
查看>>
PostgreSQL 10.1 手册_部分 III. 服务器管理_第 21 章 数据库角色
查看>>
Qt开发——网络编程UDP网络广播软件之服务器端
查看>>
Postgresql 12.9如何配置允许远程连接
查看>>
PostgreSQL 9.6 同步多副本 与 remote_apply事务同步级别 应用场景分析
查看>>
Postgresql CopyManager 流式批量数据入库
查看>>
PostgreSQL cube 插件 - 多维空间对象
查看>>
PostgreSQL Daily Maintenance - cluster table
查看>>
PostgreSQL on Linux 最佳部署手册
查看>>
PostgreSQL Oracle 兼容性之 - pipelined
查看>>
PostgreSQL Point-In-Time Recovery (Incremental Backup)
查看>>
postgresql Streaming Replication监控与注意事项
查看>>
postgresql 不需要付费_使用数据传输在PostgreSQL执行 外部连接运算符
查看>>
postgresql 主从配置_生产环境postgresql主从环境配置
查看>>
postgresql 函数&存储过程 ; 递归查询
查看>>
PostgreSQL 分组聚合查询中 filter 子句替换 case when
查看>>