Unity UI 是怎么做成工业化的体系的

Unity UI 是怎么做成工业化的体系的

在游戏开发中,UI适配是一个老生常谈但又常谈常新的话题。同一套UI要在几千种不同屏幕比例的设备上呈现出一致的效果——从4:3的iPad到21:9的带鱼屏显示器,从19.5:9的刘海屏手机到16:10的笔记本——这其中的挑战远比“拖几个锚点”要复杂得多。

市面上大型二次元游戏(如《原神》《明日方舟》《崩坏:星穹铁道》)的UI之所以能在各种设备上保持高质量呈现,靠的不是某个“魔法设置”,而是一套从Canvas到容器到内容的工业化分层适配体系

本文将带你从原理到实战,彻底搞懂Unity UI适配的每一个环节。

阅读本文前建议:打开Unity编辑器,边看边操作,理解更深。

一、第一层:Canvas —— 一切的起点

Canvas是所有UI元素的根节点,它的设置决定了整个UI系统的“世界观”。这里有两个最关键的决策:Render Mode(渲染模式)Canvas Scaler(缩放模式)

1.1 Render Mode:UI如何“画”在屏幕上

Unity Canvas提供了三种渲染模式:

模式特点使用场景
Screen Space - OverlayUI永远在最顶层,独立于摄像机渲染99%的常规UI(主界面、HUD、弹窗)高效性能交互性差,只能点击
Screen Space - CameraUI由指定摄像机渲染,可被3D物体遮挡UI与3D场景深度融合(角色展示、AR效果)有UIParticle的可以使用
World SpaceUI作为3D世界中的平面对象3D空间中的UI(血条、头顶名字)围绕玩家显示的固定小UI,常用于我们的VR游戏

为什么二游几乎全部使用Overlay模式?

因为Overlay模式稳定、高效、简单。按钮、血条、对话框这些核心UI需要始终清晰可见,不能被模型挡住,也不能因为摄像机旋转而变形。据行业统计,App Store排名前100的2D游戏中,87%使用了Screen Space - Overlay模式。

什么时候用Screen Space - Camera?当你想让3D角色“站在”UI背景板前面,或者粒子特效穿梭在UI文字之间时,才需要考虑这个模式。

1.2 Canvas Scaler:整体缩放的总指挥

Canvas Scaler是UI适配的“大脑”,它控制着整个Canvas下所有UI元素的缩放方式。

三种缩放模式

  1. Constant Pixel Size:固定像素大小,不缩放。适用于不需要适配的固定UI。

  2. Scale With Screen Size最常用模式,根据屏幕尺寸按比例缩放。

  3. Constant Physical Size:保持物理尺寸一致(考虑DPI)。

对于绝大多数游戏,我们选择Scale With Screen Size

核心参数:Reference Resolution(参考分辨率)

这是美术设计稿的基准分辨率。横屏游戏常用1920x1080,竖屏游戏常用1080x1920。所有UI元素都是在这个分辨率下设计和摆放的,Canvas Scaler负责把它们“翻译”到真实屏幕上。

核心参数:Screen Match Mode

当真实屏幕的宽高比与参考分辨率不一致时,Canvas Scaler如何取舍?这里有三个模式:

Match Width Or Height(最常用)

通过Match值(0~1)来决定适配偏向哪个轴:

  • Match = 0匹配宽度。以宽度为基准计算缩放系数,高度可能会被裁切。

  • Match = 1匹配高度。以高度为基准计算缩放系数,宽度可能会有空白。

  • Match = 0.5:宽度和高度的折中。

横屏游戏的最佳实践Match = 1(匹配高度)。因为横屏游戏的核心内容通常在水平方向展开,优先保证垂直方向填满屏幕更重要。

竖屏游戏的最佳实践Match = 0(匹配宽度)。

多端兼容的高级做法:通过代码动态计算Match值,根据当前屏幕宽高比智能切换适配策略。

Expand 和 Shrink
  • Expand:取宽高比的最小值作为缩放系数,UI永远不会被裁切,但可能出现空白。

  • Shrink:取宽高比的最大值作为缩放系数,UI永远不会出现空白,但可能被裁切。

💡 核心理解:Canvas Scaler控制的是整体UI的缩放倍率,它决定了UI在物理屏幕上是“太大”还是“太小”,但不决定每个UI元素怎么填满屏幕。后者是锚点的工作。

二、第二层:容器 —— 锚点与拉伸的博弈

Canvas Scaler搞定了“整体大小”,但每个UI元素在屏幕上的具体位置和形状,由RectTransform锚点(Anchors)轴心(Pivot)决定。

2.1 锚点(Anchors)的本质

锚点不是简单的“固定点”,而是定义了UI元素边界相对于父元素的参考系

锚点用两个坐标定义:

  • anchorMin:左下角锚点位置(0~1)

  • anchorMax:右上角锚点位置(0~1)

坐标系以父元素左下角为(0,0),右上角为(1,1)

四种锚点状态

状态anchorMin == anchorMax效果
锚点重合元素大小固定,只改变位置
锚点分离元素会拉伸以填充锚点之间的区域

2.2 “拉伸”与“固定”的底层原理

这是整个UI适配中最核心、也最容易被误解的概念。

anchorMin == anchorMax(锚点重合)

  • 元素的大小由sizeDelta决定,固定不变

  • 元素的位置由anchoredPosition决定,相对于锚点定位

  • 屏幕变大时,元素不拉伸,只是跟着锚点移动

anchorMin != anchorMax(锚点分离)

  • 元素的边缘会“粘”在锚点所在的位置

  • 父元素变大,元素的对应边跟着拉伸

  • 元素的大小由锚点之间的距离决定,动态变化

2.3 工业标准:什么元素该拉伸,什么该固定?

这不是拍脑袋决定的,而是有明确的分类逻辑:

元素类型锚点策略原因
全屏背景图四角拉伸(Stretch)必须填满整个屏幕,不能有黑边
顶部导航栏顶部拉伸(Top-Stretch)横向铺满,紧贴顶部
底部按钮栏底部拉伸(Bottom-Stretch)横向铺满,紧贴底部
居中弹窗/内容中心固定(Center)始终居中,大小不变
角落按钮(返回键)角落固定(如Bottom-Right)始终待在固定角落
Logo/标题固定位置(如Top-Left)保持设计尺寸,不被拉伸

一句话总结容器拉伸,内容固定。背景、底板、导航栏这些“容器”需要拉伸来适应屏幕;按钮、图标、文字这些“内容”需要固定来保持设计美感。

2.4 “拉伸”和“Scale”到底是什么关系?

很多初学者会困惑:“既然Canvas Scaler已经做了缩放,为什么还需要锚点拉伸?”

它们是两个完全不同层次的操作

  • Canvas Scaler(Scale):控制整体UI的缩放倍率。它让UI在物理尺寸上不显得太大或太小。

  • 锚点拉伸(Stretch):控制单个元素如何填充父容器。它让UI元素在长宽比变化时“填坑”或“让位”。

打个比方

  • Canvas Scaler 是“放大镜”,把整张设计图放大或缩小。

  • 锚点拉伸是“橡皮泥”,让背景图这块“布”跟着屏幕边缘走。

当屏幕从16:9变成21:9(更宽)时:

  • Canvas Scaler 根据Match值算出缩放系数,整体UI等比缩放

  • 拉伸的背景图会“厚着脸皮”跟着拉宽,填满多出来的区域

  • 固定的按钮则保持原大小,只是根据锚点位置整体挪动

所以,“拉伸”和“Scale”是协作关系,不是替代关系。

三、第三层:内容 —— Pivot与精确定位

当锚点确定了元素“贴在哪里”之后,Pivot(轴心)决定了元素“围绕哪个点”进行定位、旋转和缩放。

3.1 Pivot是什么?

Pivot是元素自身的局部坐标系原点。它的坐标范围是(0,0)到(1,1),以元素自身的左下角为(0,0),右上角为(1,1)

  • (0.5, 0.5):中心点(默认)

  • (0, 0):左下角

  • (1, 1):右上角

3.2 Pivot的作用

  1. 定位基准anchoredPosition描述的是Pivot相对于锚点的位置

  2. 旋转中心:元素旋转时围绕Pivot点转

  3. 缩放中心:元素缩放时以Pivot点为基准

3.3 Pivot的工业实践

在大型项目中,Pivot的设置通常遵循以下惯例:

元素类型推荐Pivot原因
普通按钮/图标(0.5, 0.5)居中定位最直观
文本/标签(0, 0.5) 或 (0.5, 1)左对齐或顶部对齐更方便
进度条(0, 0.5)从左向右填充
滑动条滑块(0.5, 0.5)居中跟随轨道

💡 技巧:按住Shift键拖动锚点预设时,可以同时设置元素的Pivot。

四、三层体系如何协同工作?

一套完整的UI适配方案是Canvas → 容器 → 内容三层协同的结果:

text

┌─────────────────────────────────────────────────────┐ │ Canvas层(整体框架) │ │ • Render Mode: Screen Space - Overlay │ │ • Canvas Scaler: Scale With Screen Size │ │ • Reference Resolution: 1920x1080 │ │ • Match: 1(匹配高度) │ │ 作用:决定UI整体的缩放倍率 │ ├─────────────────────────────────────────────────────┤ │ 容器层(布局骨架) │ │ • 背景图:四角拉伸(填满屏幕) │ │ • 导航栏:顶部拉伸(横向铺满) │ │ • 底部栏:底部拉伸(横向铺满) │ │ 作用:决定UI元素如何填充父容器 │ ├─────────────────────────────────────────────────────┤ │ 内容层(具体元素) │ │ • 按钮:固定大小 + 固定角落/居中 │ │ • 图标:固定大小 + Pivot居中 │ │ • 文本:固定大小 + Pivot按需调整 │ │ 作用:保持设计美感,不被拉伸变形 │ └─────────────────────────────────────────────────────┘

每一层解决不同的问题,缺一不可。

五、进阶话题:异形屏安全区(SafeArea)

现代手机普遍有刘海、挖孔、圆角,这些区域不能放置可交互的UI元素。

Unity提供了Screen.safeAreaAPI,返回屏幕上绝对安全的矩形区域。

工业级实现方式

  1. 创建一个“安全区容器”(SafeRect),挂载脚本

  2. 脚本在Start中读取Screen.safeArea

  3. 将安全区坐标转换为锚点值,赋值给容器的anchorMinanchorMax

  4. 所有可交互UI都放在这个容器内

这样,按钮自动避开刘海和底部横条,而背景图依然通过四角拉伸铺满整个屏幕。

六、市面二游的实践总结

基于行业观察和技术分享,大型二次元游戏的UI适配方案有以下共性:

  1. 强制横屏:《原神》《明日方舟》《崩坏:星穹铁道》均采用强制横屏设计,从根本上降低了适配复杂度。

  2. Overlay为主:99%的UI使用 Screen Space - Overlay 模式,保证稳定性和性能。

  3. Scale With Screen Size:Canvas Scaler统一设置为 Scale With Screen Size,横屏游戏 Match 值偏向 1(匹配高度)。

  4. 容器拉伸 + 内容固定:背景、底板等容器使用四角拉伸;按钮、图标等内容使用固定锚点。

  5. 安全区适配:所有可交互UI放入安全区容器,避开刘海和圆角。

  6. 多套UI预案:当横竖屏体验无法调和时,准备两套独立的UI预制体。

七、常见误区与避坑指南

❌ 误区1:“用了Canvas Scaler就不用管锚点了”

正解:Canvas Scaler管“整体大小”,锚点管“单个元素的填充方式”,两者缺一不可。

❌ 误区2:“所有UI元素都设成拉伸就完事了”

正解:按钮、图标被拉伸会变形,只有容器类元素才该拉伸

❌ 误区3:“Match值随便设,反正都能适配”

正解:Match=0和Match=1在异形屏上的表现天差地别。横屏游戏推荐Match=1,竖屏游戏推荐Match=0。

❌ 误区4:“Pivot无关紧要,默认就好”

正解:Pivot影响定位、旋转和缩放的基准点。进度条、滑动条等组件必须调整Pivot才能正常工作。

结语

Unity UI适配的本质,是把“设计稿”翻译成“真实屏幕”的过程。这个过程需要三层协作:

  1. Canvas层:用 Scale With Screen Size 控制整体缩放

  2. 容器层:用锚点拉伸让背景和底板填满屏幕

  3. 内容层:用固定锚点和Pivot保持按钮和图标的精致

记住这句口诀:“容器拉伸填满屏,内容固定保美型,Canvas缩放定大局,三层协同才可行。”

希望这篇文章能帮你从“只会拖锚点”进阶到“理解适配原理”。如果觉得有用,欢迎点赞收藏,也欢迎在评论区交流你的UI适配经验!