UGUI—深入理解Canvas Scaler屏幕自适应

3,890 阅读7分钟

前言

在学习Canvas Scaler组件之间,让我们先来了解一下什么是像素、图片分辨率、屏幕分辨率、像素比以及宽高比。

像素:像素指的是图像最小的单位,是独立的一个色块(像素点),一张图片就是由这些像素点构成的,单位面积内像素点越多,越密集,那么图像就会越清晰。

图片分辨率:图像分辨率是指每英寸图像内的像素。图像分辨率是有单位的,叫像素没英寸。分辨率越高,像素的点密度越高,图像越逼真。

屏幕分辨率:屏幕所能显示像素的多少,分辨率1920x1080的意思就是水平方向含有像素数为1920个,垂直方向像素数为1080个。屏幕尺寸一样的情况下,分辨率越高,显示效果越精细和细腻。

像素比:是指每个格子(像素)是方的还是扁的。1:1就是正方的,4:3是有点扁的,16:9是很扁。

宽高比(画面比):指视频图像的宽度和高度之间的比例。

注意:

  • 实际的屏幕宽高比不一定是分辨率之比,除非像素比是1:1。
  • 实际的屏幕宽高比 = 横向分辨率x横向像素长度:纵向分辨率x纵向像素长度。 比如一部电影,分辨率是640 * 360,画面宽高比是16:9(640:360),那么像素比正好是1:1。

Canvas Scaler

Unity官方对于Canvas Scaler的定义是"The Canvas Scaler Component is used for controlling the overall scale and pixel density of UI elements in the Canvas. This scaling effects everything under the Canvas, including font size and image borders"。意思是Canvas Scaler组件用于控制在画布上所有的UI元素的缩放比例和像素密度。并且这个缩放比例会影响所有在Canvas上面的东西,包括字体大小和图片边界。

为了适用不同分辨率,我们可能需要允许适当的UI整体性的缩放,外加一些尽可能少的局部微调,这样可以达到一个比较理想的效果。Canvas Scaler就是负责该功能的组件。

当Canvas的Render Mode为Screen Space - Overlay或者是Screen Space - Camera时,Canvas Scaler的UI Scale Model有三个选项,分别是:Constant Pixel Size、Scale With Screen Size、Constant Physical Size,如下图所示:

5.png

当Canvas的Render Mode为World Space时,Canvas Scaler的UI Scale Model只有一个为Wordl默认选项,且不可更改,如下图所示:

6.png

下面来详细介绍一下Constant Pixel Size、Scale With Screen Size、Constant Physical Size这三种模式。


UI Scale Mode — Constant Pixel Size

说明: 当屏幕分辨率设置为1000 * 1000时,创建一个Canvas,再在Canvas里面添加一张宽高为100 * 100的图片。

  • 参数详解:

    • Scale Factor:画布的缩放比例。默认为1,代表正常大小。
    • Reference Pixels Per Unit:每单位代表的像素量。
  • 当Scale Factor设置为1时,Canvas的宽高为1000 * 1000,图片的宽高为100 * 100,如下图所示: 7.png

    9.png

  • 当Scale Factor设置为2时,Canvas的宽高为500 * 500,图片的宽高还是为100 * 100,如下图所示: 8.png

    9.png 总结: 无论屏幕大小如何,UI元素都保持相同的像素大小。使用该模式时,可以在屏幕上按像素指定UI元素的位置和大小。这也是画布在未附加任何画布缩放器时的默认功能。但是借助画布缩放器中的”Scale Factor”设置,可以向画布中的所有UI元素应用常量缩放。

UI Scale Mode — Scale With Screen Szie

说明 当屏幕分辨率设置为1000 * 1000时,创建一个Canvas,再在Canvas里面添加一张宽高为800 * 600的图片,UI布局设计分辨率设置为800 * 600。

  • 参数详解:
    • Reference Resolution: UI布局的设计分辨率。
    • Screen Match Mode - Macth Width Height
      • Match是一个滑条,当Match为0时,按宽度进行Canvas等比缩放;当Match为1时,按高度进行Canvas等比缩放。一般情况下这个值非0即1,不用纠结中间值。
      • 如果屏幕分辨率小于等于设计分辨率时,那么不管Match的值是多少,Canvas的宽高都为设计分辨率。此时案例中为800 * 600.
      • 如果屏幕分辨率大于设计分辨率,那么当Match为0时,Canvas的宽为设计分辨率的宽,高再根据屏幕分辨率计算所得,这种情况案例中Canvas的宽为800,高为800;当match为1时,Canvas的高为设计分辨率的高,宽再根据屏幕分辨率计算所得,这种情况案例中的Canvas的宽为600,高为600;
        1.gif
    • Screen Match Mode - Expend
      • 当屏幕分辨率小于等于设计分辨率时,那么此时Canvas的宽高为设计分辨率800 * 600。
      • 当屏幕分辨率大于设计分辨率时,选择屏幕分辨率与设计分辨率的宽高差值较小的那个作为缩放标准,另外一个再根据屏幕分辨率进行缩放。案例中,高度差值为(1000 - 800)200,宽度差值为(1000 - 600)400,200较小,所有此时案例中Canvas的宽为800,高再根据屏幕分辨率1:1得到800。
      • 此举旨在减少扩大分辨率时由于非等比扩大而对UI整体布局造成影响。适合制作较小标准尺寸,扩充到较大屏幕。
    • Screen Match Mode - Shrink
      • 和Expend类似,但是更适合缩小的情形。
      • 选择屏幕分辨率与设计分辨率的宽高差值较大的那个作为缩放标准,另外一个再根据屏幕分辨率进行缩放。案例中,高度差值为(1000 - 800)200,宽度差值为(1000 - 600)400,400较大,600,宽再根据屏幕分辨率1:1得到600。 总结: 屏幕越大,UI元素越大。使用该模式时,可以根据指定分辨率像素来指定位置和大小,如果当前屏幕的分辨率大于参考分辨率,则画布会保持参考分辨率,但是会放大以便适应屏幕。如果当前屏幕的分辨率小于参考分辨率,则画布会相应缩小以适应屏幕。

UI Scale Mode — Constant Physical Size

说明: 与 Constant Pixel Size 模式本质相同, Constant Pixel Size 通过逻辑像素大小调节来维持缩放,Constant Physical Size 通过物理大小调节来维持缩放。使用这种模式必须指定一个像素转换物理大小的因数,运行时通过具体设备的 DPI 计算最终的 Canvas 像素大小和缩放比例。

  • 参数详解:
    • Physical Unit: 用于指定 UI 位置和大小的物理单位 属性描述计算中的 targetDPICentimeters厘米2.54Millimeters毫米25.4Inches英寸,约 25.4 毫米1Points点,1/72 英寸,1/12 派卡72Picas派卡,1/6 英寸6
    • Fallback Sprite DPI: 如果未获取到屏幕的DPI,将使用此值参与计算缩放。
    • Default Sprite DPI: 与Reference Pixels Per Unit共同计算每单位UI单位像素数。
    • Reference Pixels Per Unit: 与Default Sprite DPI共同计算每UI单位像素数。
  • 源码:
///<summary>
///Handles canvas scaling for a constant physical size.
///</summary>
protected virtual void HandleConstantPhysicalSize()
{
    float dpi = (currentDpi == 0 ? m_FallbackScreenDPI : currentDpi);
    float targetDPI = 1;
    switch (m_PhysicalUnit)
    {
        case Unit.Centimeters: targetDPI = 2.54f; break;
        case Unit.Millimeters: targetDPI = 25.4f; break;
        case Unit.Inches: targetDPI = 1; break;
        case Unit.Points: targetDPI = 72; break;
        case Unit.Picas: targetDPI = 6; break;
    }
    SetScaleFactor(dpi / targetDPI);
    //设置Canvas中每个单位有多少像素
    SetReferencePixelsPerUnit(m_ReferencePixelsPerUnit * targetDPI / m_DefaultSpriteDPI);
}

总结: 无论屏幕大小和分辨率如何,UI元素都保持相同的物理大小。使用该模式时,可以在屏幕上按照物理单位指定UI元素的位置和大小。此模式要求设备正确报告其屏幕DPI(分辨率)。对于不报告DPI的设备,可以指定回退DPI

引用参考

# Unity关于像素,Camera大小,以及分辨率的研究

# 自适应神器

# Unity UGUI-Canvas Scaler总结

# ugui源码_UGUI(二)- Canvas Scaler