You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity:如何通过代码用Canvas实现保持宽高比的全屏裁剪背景

用Canvas实现全屏等比裁剪背景图(Unity 2022.3)

需求说明

在手机端通过代码创建背景图,要求:

  • 覆盖全屏
  • 保持图片原宽高比
  • 当图片与屏幕比例不一致时,裁剪超出部分
  • 适配任意图片及屏幕尺寸

现有SpriteRenderer实现思路

已通过正交相机+SpriteRenderer实现核心逻辑:对比屏幕与图片的宽高比,调整pixelsPerUnit,让图片在比例较小时匹配屏幕宽度,比例较大时匹配屏幕高度,从而实现全屏覆盖并裁剪多余区域。

Canvas实现方案(纯代码)

核心组件配置逻辑

要实现相同效果,需用到以下组件并配置对应参数:

  • Canvas:渲染模式设为Screen Space - Overlay,无需额外相机,直接贴合屏幕
  • CanvasScaler:设置为Scale With Screen Size,确保UI适配不同分辨率
  • RawImage(推荐):承载背景纹理,相比Image更灵活处理裁剪;若用Image需先将纹理转为Sprite
  • AspectRatioFitter:强制保持图片的原始宽高比,设置AspectMode为EnvelopeParent(让图片覆盖父容器,超出部分裁剪)

完整代码片段

using UnityEngine;
using UnityEngine.UI;

public class CanvasBackgroundCreator : MonoBehaviour
{
    public Texture2D backgroundTexture; // 传入需要设置的背景纹理

    void Start()
    {
        CreateFullscreenBackground();
    }

    void CreateFullscreenBackground()
    {
        // 1. 创建Canvas根对象
        GameObject canvasGO = new GameObject("BackgroundCanvas");
        Canvas canvas = canvasGO.AddComponent<Canvas>();
        canvas.renderMode = RenderMode.ScreenSpaceOverlay; // 直接覆盖屏幕

        // 2. 配置CanvasScaler
        CanvasScaler canvasScaler = canvasGO.AddComponent<CanvasScaler>();
        canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
        canvasScaler.referenceResolution = new Vector2(1080, 1920); // 参考分辨率可自定义
        canvasScaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
        canvasScaler.matchWidthOrHeight = 0.5f; // 此处不影响背景,背景由AspectRatioFitter控制

        // 3. 创建背景RawImage对象
        GameObject backgroundImageGO = new GameObject("BackgroundImage");
        backgroundImageGO.transform.SetParent(canvasGO.transform);

        // 4. 配置RectTransform为全屏
        RectTransform imageRect = backgroundImageGO.AddComponent<RectTransform>();
        imageRect.anchorMin = Vector2.zero;
        imageRect.anchorMax = Vector2.one;
        imageRect.offsetMin = Vector2.zero;
        imageRect.offsetMax = Vector2.zero;
        imageRect.pivot = new Vector2(0.5f, 0.5f);

        // 5. 添加RawImage组件并赋值纹理
        RawImage rawImage = backgroundImageGO.AddComponent<RawImage>();
        rawImage.texture = backgroundTexture;
        rawImage.uvRect = new Rect(0, 0, 1, 1); // 显示完整纹理,裁剪由AspectRatioFitter控制
        rawImage.color = Color.white;

        // 6. 添加AspectRatioFitter,实现等比覆盖裁剪
        AspectRatioFitter aspectFitter = backgroundImageGO.AddComponent<AspectRatioFitter>();
        aspectFitter.aspectMode = AspectRatioFitter.AspectMode.EnvelopeParent;
        // 设置为图片的原始宽高比
        aspectFitter.aspectRatio = (float)backgroundTexture.width / backgroundTexture.height;
    }
}

关键细节说明

  • 为什么用RawImage?:RawImage直接使用Texture2D,无需转换为Sprite,节省资源且更灵活;若必须用Image,可将纹理转为Sprite后赋值给Image组件,开启Preserve Aspect并将RectTransform设为全屏,同样能实现裁剪效果
  • AspectMode.EnvelopeParent:该模式会让图片按原始比例放大,直到完全覆盖父容器(全屏),超出部分会被自动裁剪,正好符合需求
  • Canvas渲染模式:Screen Space - Overlay是最适合UI背景的模式,无需依赖场景相机,避免相机参数变化影响背景显示

内容的提问来源于stack exchange,提问作者AstrOne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 17:57:05