2.4 UI 缩放与安全区:手机屏幕的形状管理

核心结论

电视和 PC 显示器是规整的矩形,手机屏幕不是:刘海、灵动岛、打孔屏、圆角、手势条,都在蚕食有效显示区。UE 的 UI 系统(UMG)默认是"塞满整个屏幕"的逻辑,不管 UI 就可能被系统的刘海切掉。安全区适配是移动 UI 的及格线,不是加分项。

DPI 缩放基础

UE 的 UMG 以 1080p 为基准设计,在不同分辨率设备上靠 DPI Scale 缩放。核心设置:

  • Project Settings -> User Interface -> DPI Scale Rule:一般用 Shortest Side(短边)。
  • DPI Curve:短边 1080 时 scale=1,短边 2160 时 scale=2。

我的做法:设计画布固定 1080x1920,把 DPI 曲线调成"短边 1080 -> 1.0"。这样 iPhone 14(390pt 逻辑分辨率)和安卓中端机(1080p)上 UI 都自动缩放,美术只画一套图。

安全区(Safe Zone):不只是刘海

官方 UI 缩放指南(https://www.wanxiangyundang.top/read/unreal-engine-5-8-docs/scaling-ui-for-different-devic-2f05)里讲得最透的是:移动 UI 必须考虑四条边各自的安全区留白:

边 典型占用 处理
顶部 刘海/灵动岛/状态栏 留 SafeZone 顶部
底部 手势条(iOS)/ 导航栏(Android) 留 SafeZone 底部
左右 曲面屏误触区 留 SafeZone 左右

UMG 实操

  1. 根 Widget 的 Anchors 拉满全屏。
  2. 在最外层面板加 SafeZone 组件(不是改 Padding!)。
  3. 边距在 SafeZone 内部用 Padding 表达,而不是锚点偏移。

常见错法:用固定 Padding(如 48px)代替 SafeZone。这在某一款手机上碰巧能避开刘海,换个机型就被切。必须用 SafeZone 节点。

常见坑与解法

坑 1:UI 在一款手机上好好的,另一款被刘海切

原因:固定边距适配,没读安全区。

解法:SafeZone 节点包裹最外层;Android 上设 Project Settings -> Android -> Safe Zone 是否被某些厂商改写(部分 Android 12+ 设备 SafeZone 值需要从 java 层取)。

坑 2:横竖屏切换时 UI 错位

原因:UMG 锚点按竖屏设计,转横屏没重新布局。

解法:横竖屏用不同锚点布局;核心是用锚点+对齐而不是绝对坐标。横屏游戏直接做横屏画布。

坑 3:小屏手机字被挤碎

原因:DPI 缩放做了,但字号不存在剩余空间。

解法:字号用 Size Box + Wrap Text 组合,允许换行;或者字号直接小于控件,设计上预留弹性。

我的 UI 分层法

Root (Canvas, Anchors=Full)
 +-- SafeZone (Padding for notches)
      +-- 互动 UI(按钮等)
 +-- 无需安全区的背景图(全屏铺满,被切也无所谓)
 +-- 通知/Toast(单独 SafeZone + 动画)

分层原则:只有"必须完整显示"的元素才进 SafeZone。背景、装饰图直接铺满,被切掉不影响功能——这样做能给中间内容挤出更多空间。

相关节点速查

  • DPI:Project Settings -> User Interface
  • 安全区:UMG 的 SafeZone 组件(Safe Zone 槽位)
  • 横竖屏:Project Settings -> Orientation(Android/iOS 各自设置)

心得:UI 适配是移动项目里"低技术含量、高返工率"的环节。花一个下午把 SafeZone 分层和 DPI 曲线定好,能省掉后期几十次"在这个机型上再看一下"的来回。验收 UI 时在真机上截图,别信编辑器里的预览。