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 实操
- 根 Widget 的
Anchors拉满全屏。 - 在最外层面板加
SafeZone组件(不是改 Padding!)。 - 边距在 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 时在真机上截图,别信编辑器里的预览。
