【Unity实战】RectTransform宽高自适应

文章讲述了如何在ScrollView中使用自定义的MessageBubble组件显示动态消息,利用LayoutRebuilder实现实时高度自适应,并提醒读者注意ForceRebuildLayoutImmediate的性能影响。作者呼吁读者提供优化建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假设你做了一个ScrollView,Content下要做一个消息气泡,消息气泡本身就是一个GameObject,里头有一个Text组件,Anchor为(0.5, 1.0),组件上挂好了Content Size Fitter做纵向自适应。

然而消息气泡不能挂Content Size Fitter,因为ScrollView的Content本身就有Content Size Fitter做自适应和LayoutGroup做排版,故用代码做消息气泡的自适应。

public class MessageBubble : MonoBehaviour
{
	public TMP_Text msgText;
	private RectTransform msgRectTransform;
	private RectTransform rectTransform;
	private Vector2 msgTextOrgSize;
	private Vector2 rectTransformOrgSize;

	private void Start()
	{
		rectTransform = GetComponent<RectTransform>();
		msgRectTransform = msgText.GetComponent<RectTransform>();
		msgTextOrgSize = msgRectTransform.sizeDelta;
		rectTransformOrgSize = rectTransform.sizeDelta;
	}

	/// <summary>
	/// 展示消息内容
	/// </summary>
	/// <param name="text"></param>
	public virtual void AppendMessage(string text)
	{
		msgText.text = text;
		StartCoroutine(UpdateSize());
	}

	/// <summary>
	/// 更新RectTransform的宽高
	/// 使用前需确保Text组件加上了ContentSizeFitter,锚点在为(0.5, 1),以本脚本上的RectTransform的Top为适配点
	/// </summary>
	private IEnumerator UpdateSize()
	{
		yield return new WaitForEndOfFrame();
		LayoutRebuilder.ForceRebuildLayoutImmediate(msgRectTransform);
		float yOffset = msgRectTransform.sizeDelta.y - msgTextOrgSize.y;
		msgTextOrgSize = msgRectTransform.sizeDelta;
		rectTransform.sizeDelta = new Vector2(rectTransformOrgSize.x, rectTransform.sizeDelta.y + yOffset);
		LayoutRebuilder.ForceRebuildLayoutImmediate(transform.parent as RectTransform);
	}
}

yield return new WaitForEndOfFrame();是必要的,因为更改了Text的内容不代表它身上的Content Size Fitter会马上进行自适应,所以需要等一帧。

等完了,为了避免yOffset的计算误差,在计算前Rebuild一次保证数据精确(原先是再等一帧,但是有些时候还是有误差,不知得等多少帧才可以,故Rebuild)。

计算完毕将数值赋给消息气泡的RectTransform,然后Rebuild ScrollView的Content以应用更改。

注意!ForceRebuild非常吃性能,可能会引起卡顿,不宜频繁调用。

本脚本理论上有优化空间,由于本人水平有限,欢迎大家在评论区提出!

<think>好的,用户想了解Unity中的UI设计相关方法或教程,特别是组件布局和Canvas的使用。首先,我需要整理已有的引用内容,看看哪些信息可以直接帮助用户。引用里提到了Canvas的重要性,以及如何使用Layout Components和Canvas Scaler来实现自适应布局。还有关于动画和性能优化的部分。 用户的问题可能涉及创建Canvas、布局组件、自适应调整以及动画实现。需要分步骤讲解,确保结构清晰。首先应该从Canvas的创建开始,因为它是所有UI元素的容器,引用[2]和[5]都提到了这一点。然后介绍Rect Transform和锚点系统,这是布局的基础,引用[4]提到级布局技巧,可能涉及锚点的灵活运用。 接下来,Layout Components比如Horizontal Layout Group和Grid Layout Group,可以自动排列子元素,引用[1]和[3]有相关说明。这部分需要举例说明如何应用这些组件,让用户明白如何简化布局工作。 然后,Canvas Scaler对于不同屏幕分辨率的适配非常重要,引用[3]和[4]都强调了它的作用,需要详细解释三种缩放模式,并给出使用场景的建议。 UI动画部分,引用[1]提到了Animation和Animator组件,可以结合实例说明如何制作简单的动画,比如按钮的悬停效果。 性能优化方面,引用[1]和[4]提到减少重建和合批,需要提醒用户注意静态属性和Overdraw的问题,这可能影响游戏流畅度。 最后,组件化设计模式如引用[5]中的BasePanel,可以提升UI的可维护性,这部分可以简要介绍如何组织UI元素。 在生成相关问题的时候,要覆盖用户可能进一步询问的方向,比如Canvas Scaler的具体使用、动画实现、性能优化技巧,以及如何实现复杂布局。确保问题有针对性,帮助用户深入学习的每个关键点。</think>### Unity UI设计教程:组件布局与Canvas使用指南 --- #### 一、Canvas的创建与基本设置 1. **创建Canvas** 在Unity中,所有UI元素(如按钮、文本、图片)必须放置在`Canvas`下。通过菜单栏`GameObject > UI > Canvas`创建[^2]。 - 默认会附带`EventSystem`,用于处理UI交互事件。 - 建议将Canvas重命名为`UICanvas`以便管理[^5]。 2. **Canvas Scaler配置** `Canvas Scaler`组件是UI自适应的核心,提供三种缩放模式: - **Constant Pixel Size**:固定像素大小,适合分辨率固定的项目。 - **Scale With Screen Size**:根据屏幕尺寸动态缩放(推荐),需设置参考分辨率(如1920x1080)[^3]。 - **Constant Physical Size**:基于物理尺寸(如英寸)适配,适用于特殊设备。 --- #### 二、Rect Transform与锚点系统 1. **Rect Transform组件** - 控制UI元素的位置、大小和旋转,取代普通GameObject的Transform。 - 通过锚点(Anchors)定义元素相对于父容器的对齐方式(如居中、拉伸)[^4]。 2. **锚点实战示例** - 若需按钮始终贴附屏幕底部: - 设置锚点为底部拉伸(Bottom-Stretch)。 - 调整高度为固定值(如100px)。 --- #### 三、布局组件(Layout Components) 1. **自动排列组件** - **Horizontal/Vertical Layout Group**:水平或垂直排列子元素,自动调整间距和对齐方式[^1]。 - **Grid Layout Group**:网格布局,适用于背包、图标列表。 - **Content Size Fitter**:根据子元素动态调整容器大小。 2. **布局嵌套技巧** 组合使用多种布局组件,例如: - 外层用`Vertical Layout Group`排列多个面板。 - 每个面板内使用`Grid Layout Group`排列按钮。 --- #### 四、UI动画实现 1. **Animation与Animator** - 通过`Animation`窗口录制关键帧动画(如按钮缩放、渐隐效果)。 - 使用`Animator Controller`管理多个动画状态(如Normal/Hovered/Pressed)。 2. **代码控制动画** ```csharp public Animator uiAnimator; void Start() { uiAnimator.Play("FadeIn"); // 播放名为FadeIn的动画 } ``` --- #### 五、性能优化注意点 1. **减少Canvas重建** - 将静态UI元素(如背景)与动态元素(如血量条)分离到不同Canvas。 - 使用`CanvasGroup`控制UI组的显隐,避免频繁激活/禁用GameObject[^4]。 2. **合批与Overdraw优化** - 确保UI材质和图集共享,减少Draw Call。 - 避免多层半透明UI叠加导致Overdraw。 --- #### 六、组件化设计模式 参考引用[^5]中的`BasePanel`方法: 1. 为每个UI面板创建预制体,绑定自定义脚本(如`MenuPanel.cs`)。 2. 通过脚本控制面板的初始化、显示/隐藏逻辑。 3. 使用事件系统(如UnityEvent)实现面板间通信。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值