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
相关产品推荐
相关产品推荐

