U
20 / 22 · 11 分钟
常见问题

适配所有屏幕的 UI,包括刘海屏

简短回答

怎么让 UI 适配所有屏幕尺寸?

把 Canvas Scaler 设为 Scale With Screen Size 并给一个参考分辨率,然后把每个元素锚定到它该在的角或边。在有刘海的手机上,让一个全屏父物体去贴合 Screen.safeArea。

只在 Game view 的一种分辨率下搭出来、从没在别的分辨率下验证过的 UI,在大部分手机上都是坏的。修好它靠三件事,彼此独立:canvas 怎么缩放、每个元素锚在哪里、刘海挡住了什么。

动态图解

同样的三个元素摆在三种屏幕外形上。每一个都咬住它锚定的那个角不放,第三台机器上刘海则从安全区咬掉了一块。

1 — Canvas Scaler 决定一切的大小

Canvas 默认是 Constant Pixel Size:40 像素的按钮在任何设备上都恰好 40 像素——在笔记本上按着舒服,在 1440p 手机上却小得像粒灰。改这一个下拉框就能解决。

  1. 1

    选中 Canvas,找到 Canvas Scaler 组件,把 UI Scale Mode 设为 Scale With Screen Size。

  2. 2

    把 Reference Resolution 设成你设计时用的尺寸。竖屏手机游戏用 1080 × 1920,横屏用 1920 × 1080。

  3. 3

    把 Screen Match Mode 设为 Match Width Or Height,然后把滑块拖到 0(竖屏游戏)或 1(横屏游戏)。

2 — 锚点决定东西留在哪里

锚点说明元素正扒住父物体的哪个部位。锚在中心、往右摆 400 像素的按钮,在任何屏幕上都离中心 400 像素——在窄屏上就直接出了边界。改成锚到右侧,那么无论右边界在哪,它到右边缘的距离始终不变。

  • 每个元素锚到它视觉上归属的角或边:血条锚左上,跳跃按钮锚右下,标题锚上边中间。

  • 点选 anchor 预设时按住 Alt,元素会直接跳到那个位置,而不是只改锚点、原地不动。

  • 需要撑满宽度的东西——顶部栏、对话框——把两个 anchor 控制点拉开,让它跟着拉伸,而不是停在固定宽度上。

3 — 刘海手机上的安全区

Screen.safeArea 是系统保证不会被刘海、挖孔摄像头、圆角或手势条挡住的那块矩形。Unity 没有现成的开关:你要自己把一个 RectTransform 调到和它一致,再把 UI 放进去。

SafeAreaFitter.cs — attach to a full-screen child of the Canvas
using UnityEngine;

[RequireComponent(typeof(RectTransform))]
public class SafeAreaFitter : MonoBehaviour
{
    RectTransform rt;
    Rect last;

    void Awake()
    {
        rt = GetComponent<RectTransform>();
        Apply();
    }

    // The safe area changes when the phone rotates, so do not do this once.
    void Update()
    {
        if (Screen.safeArea != last) Apply();
    }

    void Apply()
    {
        last = Screen.safeArea;

        // Anchors are 0–1 fractions of the screen, so divide by the screen size.
        Vector2 min = last.position;
        Vector2 max = last.position + last.size;
        min.x /= Screen.width;  min.y /= Screen.height;
        max.x /= Screen.width;  max.y /= Screen.height;

        rt.anchorMin = min;
        rt.anchorMax = max;
        rt.offsetMin = rt.offsetMax = Vector2.zero;
    }
}
  • 把它挂在一个铺满全屏的 Canvas 子物体上,让 HUD 都成为这个子物体的下级。千万别挂在 Canvas 自己身上——那个 RectTransform 归 Canvas Scaler 管。

  • 背景留在外面。让背景也遵守安全区,会在刘海两侧留出难看的边条;只有必须看得见、必须点得到的东西才放进去。

  • 在编辑器里,Screen.safeArea 等于整个屏幕,所以这段代码在你 build 之前看起来像没生效。没有真机时,Device Simulator 窗口是唯一的查看办法。

发布前先检查一遍

  1. 1

    打开 Window▸General▸Device Simulator,换几台机型走一遍,记得包含一台带刘海的和一台特别长的。

  2. 2

    在 Game view 里把两个极端比例加为自定义分辨率:4:3 和 21:9。这两头都稳住的 UI,中间所有比例都稳。

  3. 3

    别只看外观,还要检查点击区域。凡是手指要按的东西都大约需要 9 mm——约合 48 个设备无关像素——哪怕在你显示器上看着很小。

做出这个的那一课

触屏操作与摇杆

这篇指南单独成篇,是一份可以直接照着做的配方。在课程里,同样的东西会作为贯穿全部五个章的那个项目的一部分来搭建 —— 镜头与操作,第 05 课。