【Unity UGUI 自动布局组(12)】
官方手册自动布局 (Auto Layout) 是 Unity 中一套强大的工具系统,它能帮助我们排列和管理游戏中的 UI 元素
一、理解自动布局系统
Unity 的自动布局系统基于 布局元素 (Layout Element) 和 布局控制器 (Layout Controller) 的概念。
- 布局元素:指具有矩形变换 (RectTransform) 的UI对象(如按钮、文本)。它们通过
LayoutElement
组件提供自身期望的尺寸信息(如最小/首选宽度高度),但不直接设置最终大小。 - 布局控制器:负责根据布局元素的属性及其自身设置,计算并控制子元素的排列方式和尺寸。主要包括:
- 水平布局组 (Horizontal Layout Group):将子物体水平排列。
- 垂直布局组 (Vertical Layout Group):将子物体垂直排列。
- 网格布局组 (Grid Layout Group):将子物体排列在网格中。
- 内容大小适配器 (Content Size Fitter):根据内容动态调整自身大小。
- 宽高比适配器 (Aspect Ratio Fitter):控制物体保持特定宽高比。
二、自动布局的常见游戏应用场景
自动布局在游戏开发中应用广泛,能显著提升开发效率和界面的一致性。
应用场景 | 说明 | 常用布局组件 |
---|---|---|
游戏主菜单/设置界面 | 确保按钮、选项列表等元素整齐排列,间距一致,并且能适应不同分辨率。 | 水平/垂直布局组、内容大小适配器 |
背包/库存系统 | 动态排列物品格子。新物品获得或消耗时,布局会自动调整。 | 网格布局组、内容大小适配器 |
商店/商城列表 | 整齐展示可购买的商品项,支持滚动浏览。 | 网格布局组、垂直布局组 |
技能栏/快捷栏 | 技能图标能均匀分布,并且在不同屏幕比例下保持相对位置。 | 水平布局组、网格布局组 |
排行榜/分数列表 | 动态生成并排列玩家数据条目。 | 垂直布局组、网格布局组 |
动态生成的内容 | 如对话选项、任务列表项,数量不确定时能自动排列。 | 垂直/水平布局组、内容大小适配器 |
三、各组件详细介绍
1. Layout Element(布局元素)- 商品属性标签
作用:为单个 UI 元素定义布局参数,告诉父级容器"我希望如何被对待"。挂载对象是Item(单个元素)。
参数:
参数 | 功能说明 | 注意事项与使用技巧 |
---|---|---|
Ignore Layout | 勾选后,布局控制器(如Layout Group)将完全忽略此元素。元素的大小和位置将不再受布局控制,你可以手动自由调整其 RectTransform 。 | 当你希望某个子物体“跳出”父布局的排列规则时使用此选项。 |
Min Width | 指定该UI元素的最小宽度。布局系统会确保元素的宽度不会小于这个值。 | 常用于确保按钮、标签等元素不会因为容器变小而被压缩得无法阅读。 |
Min Height | 指定该UI元素的最小高度。布局系统会确保元素的宽度不会小于这个值。 | 和 Min Width 类似,用于保护元素的高度下限。 |
Preferred Width | 指定该UI元素的首选宽度。当父容器有足够空间时,布局系统会尝试将元素调整至这个理想的宽度。 | 用于定义元素在空间充足时的最佳表现尺寸。空间不足时,可能无法满足。 |
Preferred Height | 指定该UI元素的首选高度。当父容器有足够空间时,布局系统会尝试将元素调整至这个理想的高度。 | 和 Preferred Width 类似,用于定义理想高度。 |
Flexible Width | 定义该UI元素在宽度方向上的相对伸缩能力,用于分配剩余的额外空间。值越大,分到的额外空间越多。值为 0 表示不伸缩。 | 这是一个相对比例值。例如,两个元素的 Flexible Width 分别为 1 和 2,则额外空间会按 1:2 的比例分配给他们。 |
Flexible Height | 定义该UI元素在高度方向上的相对伸缩能力,用于分配剩余的额外空间。值越大,分到的额外空间越多。值为 0 表示不伸缩。 | 和 Flexible Width 类似,控制高度方向的弹性。 |
Layout Priority | 当多个布局元素的需求发生冲突(例如空间不足)时,此值越高的元素,其属性(Min, Preferred, Flexible)会优先被满足。 | 用于解决布局冲突,控制哪些元素的需求更重要。默认情况下,所有元素的优先级相同。 |
工作原理与优先级
布局系统在计算最终大小时,遵循一个明确的优先级顺序:
- 首先满足
Min
:确保所有元素都不小于其设定的最小值。 - 然后分配
Preferred
:如果分配完最小值后还有剩余空间,则尝试满足各元素的首选大小。 - 最后分配
Flexible
:如果满足了所有首选大小后还有富余空间,则按照Flexible
值的比例将额外空间分配给各个元素。
简单比喻:就像分蛋糕🍰
- Min:保证每个人至少能吃到一小块。
- Preferred:如果蛋糕够大,让每个人吃到自己理想的一块。
- Flexible:如果蛋糕特别大,吃得多的人(Flexible值大)可以分到更多。
使用场景示例
假设一个水平布局(Horizontal Layout Group
)中有两个按钮(Button A 和 Button B)。
-
场景一:保持按钮最小可点击区域
- 需求:防止屏幕变窄时按钮变得太小。
- 设置:为两个按钮的
Layout Element
都设置Min Width = 100
。 - 效果:无论怎么缩小窗口,按钮宽度都不会小于100像素。
-
场景二:让一个按钮优先占用空间
- 需求:Button A 是主要按钮,希望它平时更宽。
- 设置:
- Button A:
Preferred Width = 200
,Layout Priority = 1
- Button B:
Preferred Width = 150
,Layout Priority = 0
(默认)
- Button A:
- 效果:当空间紧张时,系统会优先满足Button A的200宽度,Button B的宽度可能无法达到150。
-
场景三:让某个元素自动拉伸填满剩余空间
- 需求:让Button B填充布局排好后剩下的所有空间。
- 设置:
- Button A:
Preferred Width = 200
,Flexible Width = 0
(不拉伸) - Button B:
Preferred Width = 0
,Flexible Width = 1
(可以拉伸)
- Button A:
- 效果:Button A会保持200的宽度,Button B则会拉伸以填满父容器剩下的所有宽度。
实用建议
- 理解空间分配:
Flexible
参数是一个相对值,它决定了在分配完Min
和Preferred
后,剩余空间的分配比例,而不是直接设置大小。 - 解决冲突:当布局行为不符合预期时,检查是否有
Layout Priority
冲突,或者Min
/Preferred
值设置得是否合理。 - 配合使用:
Layout Element
需要与各种Layout Group
(水平、垂直、网格)协同工作才能发挥作用,单独附加是无效的。 - 性能注意:复杂的自动布局(尤其是嵌套)会带来计算开销。对于静态UI,可以在布局稳定后禁用布局组件以提升性能。
2. Content Size Fitter(内容尺寸适配器)- 自动包装机
作用:让容器根据其内容或子元素自动调整大小。
内容大小适配器 (Content Size Fitter) 属性
属性 (Property) | 选项 (Options) | 功能说明 (Description) |
---|---|---|
Horizontal Fit (水平适应) | Unconstrained | 宽度不受内容约束,可手动调整。 |
Min Size | 根据子布局元素(如 Text、Layout Group 等)的最小宽度自动调整自身宽度。 | |
Preferred Size | 根据子布局元素的首选宽度自动调整自身宽度。这对于文本长度变化或需要容纳特定比例的子对象非常有用。 | |
Vertical Fit (垂直适应) | Unconstrained | 高度不受内容约束,可手动调整。 |
Min Size | 根据子布局元素的最小高度自动调整自身高度。 | |
Preferred Size | 根据子布局元素的首选高度自动调整自身高度。常用于文本换行导致高度变化的情况。 |
功能与工作原理
Content Size Fitter 的主要作用是监听其子对象(或自身)上的布局元素(如 Text、Image、Layout Group 或 Layout Element 组件),获取这些元素提供的 Min Size
和 Preferred Size
等布局信息,然后根据你选择的 Fit 模式(Min Size
或 Preferred Size
)自动调整 RectTransform 的宽高。
将其设置为 Unconstrained
则不对该方向进行自动调整。
重要注意事项
-
轴心 (Pivot) 的影响:UI 元素调整大小时会围绕其轴心 (Pivot) 点进行缩放。例如:
- 轴心在中心 (0.5, 0.5):向四周均匀扩展。
- 轴心在左上角 (0, 1):向右和向下扩展。
- 根据需要调整轴心位置可以控制扩展方向。
-
与父级布局组的冲突:如果父物体上有
Layout Group
(如Vertical Layout Group
),同时子物体上有Content Size Fitter
,可能会产生布局冲突。通常的解决方案是:- 在父级
Layout Group
上禁用Child Force Expand
。 - 对于需要灵活扩展的子项,可以添加
Layout Element
组件并设置其Flexible Width/Height
。
- 在父级
-
性能与刷新:
Content Size Fitter
的尺寸调整通常在下一帧进行。若需立即刷新,可调用LayoutRebuilder.ForceRebuildLayoutImmediate(rectTransform)
强制立即重建布局。在处理大量动态内容时,需注意其对性能的潜在影响。
配合其他组件使用
- 与 Layout Group 配合:常与
Horizontal Layout Group
或Vertical Layout Group
一同使用,实现复杂自适应布局。 - 与 Layout Element 配合:
Layout Element
可覆盖默认的布局信息,用于设置最小、首选或灵活尺寸,与Content Size Fitter
配合可实现更精细的控制。
常见应用场景
- 动态文本:文本框根据文字内容自动调整大小,常用于聊天框、提示框等。
- 自适应按钮:按钮宽度随文本内容变化。
- 列表项自适应:在
Scroll View
中,列表项根据其内容(如图文混排)自动调整高度。
3. Aspect Ratio Fitter(宽高比适配器)- 比例锁定器
作用:强制 UI 元素保持特定的宽高比。
参数 (Property) | 模式 (Mode) | 效果 (Effect) | 适用场景 (Use Case) | 注意事项 (Notes) |
---|---|---|---|---|
Aspect Mode (宽高比模式) | None (无) | 不进行任何宽高比约束,UI 元素按常规布局规则显示。 | 默认状态,不需要比例控制时使用 | 此模式下,组件不生效,Rect Transform 可自由编辑。 |
Width Controls Height (宽度控制高度) | 元素的高度会根据当前宽度和设定的 Aspect Ratio 自动计算,以保持比例。 | 响应式图片、需要宽度主导高度的元素 | 此模式下,高度将变为不可手动编辑,只能通过调整宽度或修改 Aspect Ratio 来间接改变。 | |
Height Controls Width (高度控制宽度) | 元素的宽度会根据当前高度和设定的 Aspect Ratio 自动计算,以保持比例。 | 垂直布局中的头像、需要高度主导宽度的元素 | 此模式下,宽度将变为不可手动编辑,只能通过调整高度或修改 Aspect Ratio 来间接改变。 | |
Fit In Parent (适配父元素) | 元素会在保持比例的前提下,自动缩放以完全适应父物体内部,可能留有空白区域。 | 全屏展示的图片、需要完整显示内容的容器 | 此模式下,元素的锚点 (Anchor) 会自动拉伸至父物体边缘,宽度和高度都不可手动编辑。 适合确保内容完整显示。 | |
Envelope Parent (包裹父元素) | 元素会在保持比例的前提下,自动缩放以完全覆盖父物体,可能导致部分内容被裁剪。 | 背景图片、需要全覆盖父容器的元素 | 此模式下,元素的锚点 (Anchor) 会自动拉伸至父物体边缘,宽度和高度都不可手动编辑。 适合做背景图,确保全覆盖。 | |
Aspect Ratio (宽高比) | - | - | - | 设定目标宽高比,计算公式为 宽度 / 高度。 例如,16:9 的宽高比约为 1.78 (16÷9≈1.78),1:1 的正方形比例为 1.0。 添加组件时,此值默认初始化为当前 UI 元素的宽高比。 修改此值会直接影响 Aspect Mode 的效果。 |
功能与工作原理
Aspect Ratio Fitter 的核心功能是控制其所在 UI 控件(GameObject)的宽高比。 它通过调整 RectTransform 的尺寸来实现这一点。 这与 Image 组件自带的 Preserve Aspect
属性有所不同:Preserve Aspect
主要用于保持图片纹理自身的比例,而 Aspect Ratio Fitter 是控制整个 UI 控件矩形区域的比例。当控件的 RectTransform 大小因锚点或布局改变时,Aspect Ratio Fitter 能确保其按设定比例缩放,这对于需要精确定位的子控件(如根据锚点定位的冒泡框)至关重要。
重要注意事项
- 锚点 (Anchor) 的自动调整:当选择
Fit In Parent
或Envelope Parent
模式时,Unity 会自动将元素的锚点设置为拉伸至父物体边缘,此时无法手动修改锚点、宽度和高度。 - 性能影响:频繁的布局计算(尤其在复杂 UI 中)可能对性能产生影响。
- 与其他组件的交互:需要注意 Aspect Ratio Fitter 与其他布局组件(如 GridLayoutGroup)的兼容性。
- 与 Layout Element 的优先级:Aspect Ratio Fitter 的调整会覆盖 Layout Element 组件设置的布局信息(如最小、首选、灵活尺寸)。
使用场景示例
- 保持头像比例:为防止头像拉伸,可将其模式设为
Width Controls Height
或Height Controls Width
,并设置比例(如 1:1)。 - 自适应背景:为背景图片设置
Envelope Parent
模式,确保其总能覆盖整个父容器,同时保持比例不变。 - 视频播放器:确保视频区域在不同屏幕下保持正确的宽高比(如 16:9)。
组件协作关系
Aspect Ratio Fitter 常与以下组件协同工作:
-
Rect Transform:定义 UI 元素的基本布局属性(如位置、大小和锚点),Aspect Ratio Fitter 在此基础上调整宽高比。
-
Content Size Fitter:Content Size Fitter 用于根据内容自动调整 UI 元素的大小,而 Aspect Ratio Fitter 则专注于控制宽高比。在复杂布局中,两者可协同工作以实现更灵活的效果。
-
Layout Group (如 Horizontal/Vertical Layout Group):排列子元素。Aspect Ratio Fitter 可用于控制 Layout Group 本身或其子项的比例。
|
功能与工作原理
Aspect Ratio Fitter 的核心功能是控制其所在 UI 控件(GameObject)的宽高比。 它通过调整 RectTransform 的尺寸来实现这一点。 这与 Image 组件自带的 Preserve Aspect
属性有所不同:Preserve Aspect
主要用于保持图片纹理自身的比例,而 Aspect Ratio Fitter 是控制整个 UI 控件矩形区域的比例。当控件的 RectTransform 大小因锚点或布局改变时,Aspect Ratio Fitter 能确保其按设定比例缩放,这对于需要精确定位的子控件(如根据锚点定位的冒泡框)至关重要。
使用场景示例
- 保持头像比例:为防止头像拉伸,可将其模式设为
Width Controls Height
或Height Controls Width
,并设置比例(如 1:1)。 - 自适应背景:为背景图片设置
Envelope Parent
模式,确保其总能覆盖整个父容器,同时保持比例不变。 - 视频播放器:确保视频区域在不同屏幕下保持正确的宽高比(如 16:9)。
重要注意事项
- 锚点 (Anchor) 的自动调整:当选择
Fit In Parent
或Envelope Parent
模式时,Unity 会自动将元素的锚点设置为拉伸至父物体边缘,此时无法手动修改锚点、宽度和高度。 - 性能影响:频繁的布局计算(尤其在复杂 UI 中)可能对性能产生影响。
- 与其他组件的交互:需要注意 Aspect Ratio Fitter 与其他布局组件(如 GridLayoutGroup)的兼容性。
- 与 Layout Element 的优先级:Aspect Ratio Fitter 的调整会覆盖 Layout Element 组件设置的布局信息(如最小、首选、灵活尺寸)。
组件协作关系
Aspect Ratio Fitter 常与以下组件协同工作:
- Rect Transform:定义 UI 元素的基本布局属性(如位置、大小和锚点),Aspect Ratio Fitter 在此基础上调整宽高比。
- Content Size Fitter:Content Size Fitter 用于根据内容自动调整 UI 元素的大小,而 Aspect Ratio Fitter 则专注于控制宽高比。在复杂布局中,两者可协同工作以实现更灵活的效果。
- Layout Group (如 Horizontal/Vertical Layout Group):排列子元素。Aspect Ratio Fitter 可用于控制 Layout Group 本身或其子项的比例。
4. Horizontal/Vertical Layout Group(水平/垂直布局组)- 流水线排列员
作用:将子元素按水平或垂直方向自动排列。
这两个组件是 Unity 自动布局系统中最核心、最常用的部分,它们的参数几乎完全相同,唯一的本质区别是排列方向。
参数 (Property) | 功能说明 (Description) | 注意事项与技巧 (Notes & Tips) |
---|---|---|
Padding (内边距) | 布局组边缘与其内部所有子物体之间的空白距离。 | 分为 Left, Right, Top, Bottom。用于控制整个容器内部的留白,类似于 CSS 中的 padding 。 |
Spacing (间距) | 各个子物体之间的间隔距离。 | 在水平布局中,这是子物体之间的水平间距;在垂直布局中,则是垂直间距。 |
Child Alignment (子物体对齐) | 当所有子物体的总尺寸小于布局组本身尺寸时,子物体们作为一个整体在布局组内的对齐方式。 | 这是一个 TextAnchor 类型的值(如 UpperLeft, MiddleCenter 等)。注意:当内容总尺寸大于布局组时,此设置通常无效,内容会溢出。具体介绍下表 |
Control Child Size (控制子物体尺寸) | 是否允许布局组强制修改子物体的尺寸。 | 勾选后,下方的 Child Force Expand 和子物体的 LayoutElement 设置才会生效。 |
Use Child Scale (使用子物体缩放) | 在计算布局位置时,是否考虑子物体的缩放值 (Scale)。 | 如果子物体被缩放了(例如 Scale 设为 0.5),勾选此项会使布局组根据缩放后的尺寸进行排列。通常保持默认(不勾选)。 |
Child Force Expand (子物体强制扩展) | 强制子物体在布局方向上扩展以填充剩余空间。 | 水平布局中勾选 Width :所有子物体将平分剩余的水平空间。垂直布局中勾选 Height :所有子物体将平分剩余的垂直空间。此设置会覆盖子物体自身 LayoutElement 的 Flexible Width/Height 设置。 |
Child Alignment 枚举详解
Child Alignment
是一个 TextAnchor
类型的值,它决定了当所有子物体的总尺寸小于布局组自身尺寸时,这个“子物体组”作为一个整体在父容器中的对齐位置。
枚举值 | 名称 | 在水平布局组中的表现 | 在垂直布局组中的表现 | 经典应用场景 |
---|---|---|---|---|
UpperLeft | 左上对齐 | 整体紧贴容器的左上角 | 整体紧贴容器的左上角 | 标签页、小地图UI元素 |
UpperCenter | 上中对齐 | 整体位于容器顶部中央 | 整体位于容器顶部中央 | 顶部状态栏、导航栏 |
UpperRight | 右上对齐 | 整体紧贴容器的右上角 | 整体紧贴容器的右上角 | 关闭按钮、金币计数 |
MiddleLeft | 左中对齐 | 整体位于容器左侧中间 | 整体位于容器左侧中间 | 侧边工具栏 |
MiddleCenter | 中心对齐 | 整体位于容器的正中心 | 整体位于容器的正中心 | 弹窗内容、主按钮 |
MiddleRight | 右中对齐 | 整体位于容器右侧中间 | 整体位于容器右侧中间 | 聊天列表、好友栏 |
LowerLeft | 左下对齐 | 整体紧贴容器的左下角 | 整体紧贴容器的左下角 | 对话输入框、技能栏 |
LowerCenter | 下中对齐 | 整体位于容器底部中央 | 整体位于容器底部中央 | 底部菜单栏、操作提示 |
LowerRight | 右下对齐 | 整体紧贴容器的右下角 | 整体紧贴容器的右下角 | 任务追踪、缩放控件 |
工作机制
1. 与 Layout Element
的协作
这是理解自动布局的关键。子物体上的 Layout Element
组件用于向父布局组 “提出需求”:
Min Width/Height
: “我至少需要这么大空间。”Preferred Width/Height
: “如果空间充足,这是我理想的尺寸。”Flexible Width/Height
: “如果还有多余空间,我愿意按这个比例分一些。”
布局组作为“经理”,会综合考虑所有“员工”(子物体)的需求,并结合自己的规则(如 Child Force Expand
),做出最终的空间分配决策。Child Force Expand
的优先级高于子物体的 Flexible
值。
2. 性能提示
- 嵌套损耗: 嵌套使用布局组(例如一个垂直布局组里包含多个水平布局组)会带来性能损耗,因为需要多次递归计算。应尽量避免过深的嵌套。
- 静态优化: 对于内容不会变化的静态UI,可以在布局完成后禁用布局组件以提升性能。
- 强制刷新: 如果在运行时通过代码修改了布局属性,可能需要调用
LayoutRebuilder.ForceRebuildLayoutImmediate(rectTransform)
来立即刷新布局,而不是等待下一帧。
常用配置示例
-
均匀分布的水平导航栏
- Padding:
Left
/Right
为 10,让两边有留白。 - Spacing: 20,让按钮之间有间隔。
- Child Alignment:
MiddleCenter
。 - Control Child Size: 勾选。
- Child Force Expand: 勾选
Width
。这样所有按钮会均匀拉宽,填满整个导航栏。
- Padding:
-
靠右排列的垂直按钮列表
- Padding: 根据需要设置。
- Spacing: 10。
- Child Alignment:
TopRight
(垂直布局中,Top
表示从顶部开始,Right
表示整体右对齐)。 - Control Child Size: 不勾选(如果你希望每个按钮保持自己的原始宽度)。
- Child Force Expand: 不勾选。
-
网格状布局 (使用多个布局组嵌套)
- 外层:
Vertical Layout Group
(Spacing = 10) - 内层:多个
Horizontal Layout Group
(Spacing = 10, 不勾选Child Force Expand
) - 这样可以实现一个行和列都有间隔的网格,每行的单元格不会相互拉伸。
- 外层:
布局流程:
5. Grid Layout Group(网格布局组)- 仓库货架管理员
作用:将子元素排列在固定网格中,像仓库货架一样整齐。
参数 (Property) | 功能说明 (Description) | 注意事项与技巧 (Notes & Tips) |
---|---|---|
Padding (内边距) | 网格边缘与所有子物体之间的空白距离。 | 分为 Left, Right, Top, Bottom。用于控制整个网格容器内部的留白。 |
Cell Size (单元格大小) | 网格中每个单元格(格子)的宽度和高度。 | 这是最常用的参数,直接控制每个格子的大小,从而决定放入其中的元素(如图标)的占位空间。 |
Spacing (间距) | 网格中单元格之间的间隔距离。 | 分为 X (水平间距) 和 Y (垂直间距)。用于控制格子与格子之间的空隙。 |
Start Corner (起始角) | 布局开始填充的第一个单元格的位置。 | 决定子元素从网格的哪个角落开始排列。 |
Start Axis (起始轴) | 布局的优先填充方向。 | Horizontal (水平):先填满一行,再换到下一行。 Vertical (垂直):先填满一列,再换到下一列。 |
Child Alignment (子物体对齐) | 当整个网格的总尺寸小于布局组自身尺寸时,网格整体在父容器内的对齐方式。 | 与水平/垂直布局组中的含义相同,是控制整个网格块的对齐,而非单个单元格内的对齐。 |
Constraint (约束) | 对网格的行数或列数进行限制。 | 这是实现固定行列布局的关键参数。 |
参数补充
1. Constraint (约束) 模式详解
此参数用于创建固定结构的网格,是网格布局的核心之一。
约束模式 | 功能说明 | 应用场景 |
---|---|---|
Flexible (灵活) | 不限制行数和列数。根据容器大小、单元格尺寸和间距,自动计算可以容纳的行和列。 | 通用的物品栏、图库,数量不固定时使用。 |
Fixed Column Count (固定列数) | 指定网格的列数。行数会根据子物体数量自动计算。 (Constraint Count 生效) | 背包界面(如固定5列)、主菜单按钮栏(固定1列)。 |
Fixed Row Count (固定行数) | 指定网格的行数。列数会根据子物体数量自动计算。 (Constraint Count 生效) | 横向卷轴游戏的技能栏(固定1行)、音乐播放器的播放列表(固定显示10行)。 |
2. Start Corner (起始角) 枚举详解
此参数决定了布局的起点,可以创造出不同的填充顺序。
起始角选项 | 填充顺序(以3x3网格为例) | 视觉描述 |
---|---|---|
Upper Left (左上角) | 1 → 2 → 3 4 → 5 → 6 7 → 8 → 9 | 从左上角开始,向右填充,填满一行后换到下一行。 |
Upper Right (右上角) | 3 → 2 → 1 6 → 5 → 4 9 → 8 → 7 | 从右上角开始,向左填充,填满一行后换到下一行。 |
Lower Left (左下角) | 7 → 8 → 9 4 → 5 → 6 1 → 2 → 3 | 从左下角开始,向右填充,填满一行后换到上一行。 |
Lower Right (右下角) | 9 → 8 → 7 6 → 5 → 4 3 → 2 → 1 | 从右下角开始,向左填充,填满一行后换到上一行。 |
3. Start Axis (起始轴) 模式详解
此参数决定了填充的优先方向,会显著影响动态生成物品时的排列顺序。
起始轴选项 | 填充顺序(以9个物品为例) | 适用情况 |
---|---|---|
Horizontal (水平) | [1, 2, 3] [4, 5, 6] [7, 8, 9] | 最常用。符合大多数阅读和排列习惯(从左到右,从上到下)。 |
Vertical (垂直) | [1, 4, 7] [2, 5, 8] [3, 6, 9] | 不常见。用于需要先填满一列再填充下一列的特殊布局。 |
常用配置示例
-
标准背包/物品栏
Cell Size
: (80, 80) // 80x80的格子Spacing
: (5, 5) // 格子间距5像素Constraint
:Fixed Column Count
// 固定列数Constraint Count
: 5 // 每行5个物品Start Corner
:Upper Left
// 从左上开始Start Axis
:Horizontal
// 水平优先填充
-
横向技能栏
Cell Size
: (60, 60)Spacing
: (2, 0) // 只有水平间距Constraint
:Fixed Row Count
// 固定行数Constraint Count
: 1 // 只有一行Child Alignment
:Middle Center
// 整体居中
-
图库/相册(灵活布局)
Cell Size
: (100, 100)Spacing
: (10, 10)Constraint
:Flexible
// 不固定行列,自动换行Start Corner
:Upper Left
Start Axis
:Horizontal
注意事项与技巧
- 性能影响:网格布局需要计算所有子元素的位置,子元素数量极大(如成百上千)时可能引起性能问题。对于长列表,建议结合
Scroll Rect
并使用对象池技术动态创建和回收元素。 - 与
Layout Element
的冲突:Grid Layout Group
会强制所有子元素的大小等于Cell Size
。子物体上Layout Element
组件设置的Preferred
或Flexible
尺寸通常会被忽略。如果需要不同大小的单元格,可能需要使用多个嵌套的布局组或自定义布局脚本。 - 动态添加子物体:在运行时添加或移除子物体会自动触发布局的重建,无需手动刷新。
- 锚点 (Anchor) 覆盖:添加到
Grid Layout Group
下的子物体,其锚点会被布局系统覆盖和驱动,手动设置的锚点可能失效。
四、实际应用场景
场景 1:响应式聊天界面
// 聊天消息容器
VerticalLayoutGroup chatContainer = GetComponent<VerticalLayoutGroup>();
ContentSizeFitter fitter = GetComponent<ContentSizeFitter>();
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;// 每条消息是一个水平布局组
HorizontalLayoutGroup messageLayout = messageObj.AddComponent<HorizontalLayoutGroup>();
messageLayout.childAlignment = TextAnchor.UpperLeft;
messageLayout.padding = new RectOffset(10, 10, 5, 5);
场景 2:自适应卡片列表
// 卡片容器使用网格布局
GridLayoutGroup cardContainer = GetComponent<GridLayoutGroup>();
cardContainer.cellSize = new Vector2(300, 200);
cardContainer.spacing = new Vector2(20, 20);
cardContainer.constraint = GridLayoutGroup.Constraint.Flexible;// 每张卡片有自己的宽高比限制
AspectRatioFitter cardFitter = cardObj.AddComponent<AspectRatioFitter>();
cardFitter.aspectMode = AspectRatioFitter.AspectMode.FitInParent;
cardFitter.aspectRatio = 1.5f; // 3:2 比例
场景 3:设置菜单选项
// 选项容器使用垂直布局
VerticalLayoutGroup optionsGroup = GetComponent<VerticalLayoutGroup>();
optionsGroup.spacing = 15;
optionsGroup.padding = new RectOffset(20, 20, 30, 30);// 每个选项项是水平布局
HorizontalLayoutGroup optionItem = optionObj.AddComponent<HorizontalLayoutGroup>();
optionItem.childForceExpandWidth = false;
optionItem.childForceExpandHeight = true;// 标签有固定宽度,滑块可拉伸
LayoutElement labelLayout = labelObj.AddComponent<LayoutElement>();
labelLayout.preferredWidth = 150;LayoutElement sliderLayout = sliderObj.AddComponent<LayoutElement>();
sliderLayout.flexibleWidth = 1; // 可拉伸
🔄 组件协作关系
五、性能优化建议
-
避免频繁布局重建:
// 批量更新时先禁用布局 layoutGroup.enabled = false; // ... 进行多个修改 ... layoutGroup.enabled = true; LayoutRebuilder.ForceRebuildLayoutImmediate(rectTransform);
-
合理使用 Canvas 组件:
- 静态内容:标记为
Canvas.Static
- 动态内容:使用
CanvasGroup
控制透明度
- 静态内容:标记为
-
嵌套布局优化:
// 避免过深的嵌套层级 // 坏:Panel -> Vertical -> Horizontal -> Grid -> Element // 好:Panel -> Grid -> Element
-
对象池与布局:
// 使用对象池时,回收前重置布局属性 void ResetElement(GameElement element) {element.transform.SetParent(null);LayoutElement layout = element.GetComponent<LayoutElement>();if (layout != null) Destroy(layout); }
六、 总结
自动布局使用期起来很是方便,但是存在性能问题,自动布局需要递归计算所有子元素的尺寸和位置。嵌套越深,计算量越大。当任何元素发生变化时,都可能触发整个布局的“脏标记”和重建。所以当Item数量较多时候,就会造成卡顿,解决办法可以使用手动计算布局+对象池。(无限滚动高性能实现思路)