浅谈UGUI中Canvas RectTransform的Scale

本文详细解析了Unity中Canvas的RectTransform组件的Scale值如何受Canvas的RenderMode和CanvasScaler的UIScaleMode设置影响。在ScreenSpace-Overlay模式下,Scale不可直接修改,需通过CanvasScaler的ScaleFactor调整。而在WorldSpace模式下,Scale可直接修改。对于ScreenSpace-Camera模式,Scale由引擎自动计算且不可更改。此外,文章还介绍了正交相机设置与Canvas Scale的关系,并给出了推荐的Size设置规则。对于SpriteRenderer组件,作者建议遵循特定的Size设置原则。

前言

Canvas的Rect Transform组件的Scale值和Canvas组件的Render Mode,以及Canvas Scaler组件的UI Scale Mode设置有关。

当Render Mode为Screen Space - Overlay:

  • UI Scale Mode为Constant Pixel Size时
    默认情况下Canvas的Rect Transform组件的Scale值为1,且界面中修改Rect Transform的Scale的区域灰化,不可操作。
    若要修改Rect Transform的Scale,可以通过修改Canvas Scaler组件的Scale Factor来实现。

当Render Mode为World Space

UI Scale Mode只有World这一项,Scale值默认为1,但是可以修改。

当RenderMode为Screen Spcae - Camera

该模式下Scale值是由引擎内部自动计算得到的,且不能修改。

该模式依赖一个Camera,通常情况下在UI系统中我们会使用正交相机。下文详细探讨正交相机模式下的Scale值,透视相机后面有空再推导。

假设当前屏幕的高度为ScreenH,正交相机有个用户可以设置的参数Size,那么有公式如下:

ScreenH*Scale*
<think>我们正在分析UnityUGUICanvas的源码实现。根据用户提供的引用,特别是引用[2]提到“UGUI源码分析”,但引用内容中并未给出具体源码分析细节。因此,我们需要结合Unity官方提供的UGUI源码仓库进行说明。UnityUGUI的源码托管在GitHub上:https://github.com/Unity-Technologies/uGUI.git由于用户要求分析Canvas的源码实现,我们应关注Canvas组件相关的代码。在UGUI源码中,Canvas相关的核心代码位于:-`UnityEngine.UI/UI/Core/Canvas.cs`-另外,Canvas的渲染和更新机制可能还涉及`CanvasRenderer`、`CanvasUpdate`等。###核心功能分析1.**Canvas组件**:负责管理UI元素的渲染。它决定UI元素是渲染在屏幕空间还是世界空间,并处理渲染顺序(通过SortingLayer和OrderinLayer)。2.**Canvas的渲染流程**:-当Canvas组件的`renderMode`设置为`ScreenSpaceOverlay`时,UI元素直接在屏幕上渲染,不需要摄像机。-当设置为`ScreenSpaceCamera`或`WorldSpace`时,需要指定一个摄像机,UI元素将在这个摄像机所定义的视口中渲染。3.**Canvas的更新**:-UGUI使用脏标记系统(DirtyFlags)来标记需要更新的UI元素。当UI元素发生变化(如位置、大小、颜色等)时,会标记为脏,然后在下一帧进行重新构建(Rebuild)。-Canvas组件本身会注册到CanvasUpdateRegistry中,在渲染前执行重建(Rebuild)和布局(Layout)更新。###源码关键点在`Canvas.cs`中,我们可以找到以下关键部分:```csharpnamespaceUnityEngine.UI{[DisallowMultipleComponent][RequireComponent(typeof(CanvasRenderer))][AddComponentMenu("UI/Canvas",10)][ExecuteAlways]publicclassCanvas:Behaviour{//...省略部分代码...//渲染模式[SerializeField]privateRenderModem_RenderMode=RenderMode.ScreenSpaceOverlay;publicRenderModerenderMode{get{returnm_RenderMode;}set{m_RenderMode=value;}}//当渲染模式为ScreenSpaceCamera或WorldSpace时使用的摄像机[SerializeField]privateCameram_WorldCamera;publicCameraworldCamera{get{returnm_WorldCamera;}set{m_WorldCamera=value;}}//...其他属性和方法...//标记Canvas为脏,需要更新publicvirtualvoidRebuild(CanvasUpdateexecuting){if(executing==CanvasUpdate.Prelayout){//执行预布局更新}//...其他更新阶段...}//...其他代码...}}```###Canvas的更新机制Canvas的更新由`CanvasUpdateRegistry`管理。这个类维护了两个列表:需要布局重建的组件列表和需要图形重建的组件列表。在每一帧的预渲染阶段(通过`Canvas.willRenderCanvases`事件),这些重建操作会被执行。###性能优化相关-**避免频繁的Canvas重建**:因为重建操作(尤其是布局重建)可能很昂贵,所以应尽量减少UI元素的变动,尤其是涉及布局变化的操作。-**使用多个Canvas**:将频繁更新的UI元素和静态UI元素分开放在不同的Canvas上,可以减少重建的范围。因为每个Canvas独立重建,这样静态部分就不会被频繁重建影响。###引用说明根据引用[1][2][3][4][5],它们提供了关于Canvas组件的基础知识、优化方法和使用示例,但未深入源码。因此,我们的源码分析主要基于官方源码仓库。###相关问题§§相关问题§§1.Canvas的渲染模式有哪些?它们分别适用于什么场景?2.如何优化Canvas的重建性能?3.Canvas的脏标记系统是如何工作的?4.在UGUI中,CanvasUpdateRegistry的作用是什么?5.为什么需要将UI元素分层到多个Canvas上?</think>### Unity UGUI Canvas 源码分析 #### 1. **Canvas 核心功能** CanvasUGUI 的渲染容器,负责管理 UI 元素的绘制顺序和渲染模式。关键源码位于: - `Canvas.cs`(核心逻辑) - `CanvasRenderer.cs`(渲染实现) - `CanvasUpdateRegistry.cs`(更新调度) 在 `Canvas.cs` 中,核心属性包括: ```csharp public class Canvas : Behaviour { public RenderMode renderMode; // 渲染模式(ScreenSpaceOverlay/ScreenSpaceCamera/WorldSpace) public Camera worldCamera; // 关联的摄像机 public float planeDistance; // UI平面与摄像机的距离 // ... } ``` [^2] #### 2. **渲染流程** - **脏标记系统**:当 UI 元素属性(位置、颜色等)变化时,标记 `Graphic` 为脏,触发重建。 - **渲染队列**:通过 `CanvasRenderer` 将顶点数据提交到 Unity 渲染管线。 - **层级排序**:由 `SortingLayer` 和 `Order in Layer` 控制绘制顺序。 关键代码片段(简化): ```csharp // CanvasRenderer.cs protected void SetVertices(List<UIVertex> vertices) { // 将顶点数据传递给底层渲染系统 InternalSetVertices(vertices); } ``` #### 3. **性能优化机制** - **静态批处理**:未变化的 UI 元素合并批次(通过 `CanvasRenderer.cull` 检测)。 - **动态重建**:仅重绘脏区域(由 `CanvasUpdateRegistry` 管理): ```csharp // CanvasUpdateRegistry.cs private void PerformUpdate() { // 遍历所有脏元素并重建 foreach (var element in m_LayoutRebuildQueue) { element.Rebuild(CanvasUpdate.Layout); } } ``` [^1][^2] #### 4. **与 Canvas Scaler 协同** `CanvasScaler.cs` 处理分辨率适配: - 根据 `Screen.width/height` 动态缩放 UI。 - 支持三种模式:`Constant Pixel Size`、`Scale with Screen Size`、`Constant Physical Size`。 #### 5. **关键设计思想** 1. **事件驱动更新**:基于 `UnityEngine.EventSystems` 的事件系统触发 UI 刷新。 2. **组件解耦**:`Canvas` 仅管理容器状态,具体渲染由 `Graphic` 派生类(如 `Image`)实现。 3. **异步重建**:通过 `Canvas.willRenderCanvases` 事件在渲染前统一处理更新。 > 提示:完整源码可查看 [Unity UGUI GitHub 仓库](https://github.com/Unity-Technologies/uGUI.git)[^1]。 --- ### 相关问题
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iningwei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值