UGUI学习笔记之Canvas Scaler组件

UI自适应

  在学习Canvas Scaler组件之前,先来了解一下UI自适应,UI自适应就是让我们的UI可以在不需要对每种分辨率的屏幕上都设计一种UI布局,而只需要在开发的时候设计一种UI布局的情况下,就可以让UI在不同分辨率的屏幕上都能尽量正常的显示,这将会节省巨大的工作量。

  而这一次要学习的Canvas Scaler组件就是用来快速的实现UI自适应功能的组件。

 

Canvas Scaler组件

官方文档:https://docs.unity3d.com/cn/current/Manual/script-CanvasScaler.html

画布缩放器组件用于控制画布中 UI 元素的整体缩放和像素密度。此缩放会影响画布下的所有内容,包括字体大小和图像边框。我们可以利用该组件去缩放全部UI元素从而适配不同分辨率的屏幕。

Canvas Scaler组件有三种模式,依次介绍

属性 说明
UI Scale Mode 缩放模式
    Constant Pixel Size 无论屏幕大小如何,UI 元素都保持相同的像素大小。
    Scale With Screen Size 屏幕越大,UI 元素越大。常用来设置UI自适应。
    Constant Physical Size 无论屏幕大小和分辨率如何,UI 元素都保持相同的物理大小。

第一种模式 Constant Pixel Size

这个模式也是在Canvas在没有附加任何Canvas scaler情况下的默认功能。但是,借助Canvas Scaler中的“Scale Factor”属性,可以自由设定UI元素缩放的比例。

在这种模式下,锚点如果采用“矩形模式”(我自己取得名字)就会呈现一种在Rect Transform中提到的缩放效果,不过看起来挺奇怪的

 

 在这种模式下,锚点如果采用“点模式”(还是我自己取得名字)也依然会按照在Rect Transform中提到的固定效果。但需要注意的是,这个时候UI元素的效果就会像该元素的名字一样,保持像素大小不变,不管屏幕大小如何变动。

功能 说明
Scale Factor 按此系数缩放画布中的所有 UI 元素,即这个数是全部UI元素的缩放比例。
Reference Pixels Per Unit 如果精灵具有此“Pixels Per Unit”设置,则精灵中的每个像素将覆盖 UI 中的一个单位。

Constant Pixel Size模式下,用代码实现UI自适应

 在这种模式下,不管屏幕大小如何变化,UI元素会保持原大小不变。但是我们可以通过Scale Factor去缩小放大这些UI元素,缩放是按照UI元素原比例进行缩放,所以要实现UI自适应关键是确定Scale Factor设为多大值。

   可以看出,当屏幕尺寸发生变化时,UI元素无非是太宽,太长或者既太宽又太长而造成重叠。

   通常屏幕尺寸变化要同时考虑宽、高两边的变化。但是我们只能设置一个缩放比例Scale Factor。因此要实现能用的UI自适应就要在这个系数上面做文章。

  为了便于理解,先只考虑一侧的变化,这里拿宽度举例。

    1.首先所有的UI元素的锚点要为“点模式”(可以将锚点放在四个角之一,这样UI元素距离四个角的距离不变),这样所有UI元素才能统一实现原比例显示。

    2.在代码中将“运行时的屏幕宽度”除以“编辑时的屏幕宽度”,将Scale Factor的值设为该值,从而让所有UI元素缩放相应倍数。为了方便观察我把自适应代码放在了Update函数,实际上只需要放在Start函数中,运行一次即可。

    void Start()
    {
        canvasScaler = GetComponent<CanvasScaler>();

    }

    // Update is called once per frame
    void Update()
    {
        //获取运行时的屏幕分辨率
        screenWidth = UnityEngine.Screen.width;
        screenHeight = UnityEngine.Screen.height;
        //编辑时屏幕分辨率为650x400
        //将ScaleFactor设为  实际屏幕宽度/编辑时屏幕宽度
        canvasScaler.scaleFactor = screenWidth / 650;
       
    }

  效果:当屏幕宽度随意变化,UI元素能随之按比例缩放。但当屏幕高度变化时,UI无变化,有可能会发生UI元素重叠的情况。

当同时考虑宽和高的变化时,可以有很多方案。这里记录三种:

方案一:按宽高权重大小决定最终缩放效果

  方案逻辑:

    分别计算出宽高的缩放比例,再根据权重来分配宽缩放比例、高缩放比例对最终效果的影响程度。

    这个方案可以选择宽、高的缩放分别对最终结果的影响大小。

  代码:

 void Update()
    {
            //获取运行时的屏幕分辨率
            screenWidth = UnityEngine.Screen.width;
            screenHeight = UnityEngine.Screen.height;        
            //总之,应当随下面两个浮点数的较小那个变化
            float w = screenWidth / 650;
            float h = screenHeight / 400;
            //编辑时屏幕分辨率为650x400
            canvasScaler.scaleFactor = propotion * h + (1 - propotion) * w;
    
        }    

  效果:当propotion为0时,只有宽度会影响UI缩放,高度不影响。当propotion为1时,只有高度会影响UI缩放,宽度不会。而propotion在0~1之间时,宽高按权重影响UI缩放。在某些分辨率下也会出现UI重叠的情况。

方案二 :按缩放比例较小的那一侧缩放:

  方案逻辑:

    1.如果高、宽两侧中有一侧缩小一侧放大,那么就取缩小那一侧的值

    2.如果高、宽两侧都缩小,那么就取缩小程度较大的那一侧的值

    3.如果高、宽两侧都放大,那么就取放大程度较小的那一侧的值

    总之就取  实际屏幕高/编辑时屏幕高   实际屏幕宽/编辑时屏幕宽  较的那个值

  代码:为了更好观察才放在了Update函数中,实际上只需要放在Start函数中,运行一次即可。

 void Update()
    {
            //获取运行时的屏幕分辨率
            screenWidth = UnityEngine.Screen.width;
            screenHeight = UnityEngine.Screen.height;        
            //总之,应当随下面两个浮点数的较小那个变化
            float w = screenWidth / 650;
            float h = screenHeight / 400;
            //编辑时屏幕分辨率为650x400
            if (w < h)
                canvasScaler.scaleFactor = w;
            else
                canvasScaler.scaleFactor = h;

        }

 效果:当屏幕宽度随意变化,UI元素能随之按比例缩放,UI不会发生重叠。但如果有背景UI,就会发现当屏幕大小发生变化时,如果宽高变化率不同就会相比原来多扩展(expand)出一部分空白(下图呈黑色)。

 

 

方案三:按缩小比例较大的那一侧缩放

  方案逻辑:

    1.如果高、宽两侧中有一侧缩小一侧放大,那么就取放大那一侧的值

    2.如果高、宽两侧都缩小,那么就取缩小程度较小的那一侧的值

    3.如果高、宽两侧都放大,那么就取放大程度较大的那一侧的值

    总之就取  实际屏幕高/编辑时屏幕高   实际屏幕宽/编辑时屏幕宽  较的那个值

  代码:为了更好观察才放在了Update函数中,实际上只需要放在Start函数中,运行一次即可。

 void Update()
    {
            //获取运行时的屏幕分辨率
            screenWidth = UnityEngine.Screen.width;
            screenHeight = UnityEngine.Screen.height;        
            //总之,应当随下面两个浮点数的较小那个变化
            float w = screenWidth / 650;
            float h = screenHeight / 400;
            //编辑时屏幕分辨率为650x400
            if (w > h) //只需要把这里的<改成>
                canvasScaler.scaleFactor = w;
            else
                canvasScaler.scaleFactor = h;
        }

  效果:在一定程度上能够自适应,但是会出现UI元素重叠的情况.如果有背景UI就可以发现,随屏幕变化背景UI会出现裁剪的情况。

 

 

 

 

  三种方案的总结:

    方案一:可以通过调整权重,来影响在不同分辨率屏幕的效果。最终可以通过不断调整数值选择一种在所有已知的分辨率里面平均效果不错的权重。

    方案二:在所有分辨率里面UI均不会重叠,可以自动缩放。但是可能会在某些分辨率下的效果不好,比如缩得太小。

    方案三:在宽、高变化程度差不多得情况下得效果和方案二差不多,但是有一点点视觉上得区别。不适合宽高比例变化程度差异很大得情况。

    这三种方案并不需要手写代码,可以直接设置,怎么设置看下面。

 

第二种模式 Scale With Screen Size

 

属性 说明
Reference Resolution 参考分辨率/编辑时的分辨率/设计UI布局时的分辨率
Screen Match Mode

当实际分辨率与参考分辨率(Reference Resolution)不同时,缩放画布的模式。这个属性就是用来直接设置上面那三种方案的。

Match Width or Height 仅以宽度或高度或按二者的某种权重比值对画布进行缩放,这一项和上面的方案一类似,但是效果有些差异,估计是计算方法有异,权重具体看Match属性。

Expand 水平和垂直方向都会缩放,经过测试,此项效果和上面的方案二效果一模一样。

Shrink 经过测试,此项效果和上面的方案三效果一模一样。

偶然间发现自己上面手写的三个方案的代码功能竟然和这里一样,所以我有理由猜测这个模式是基于Constant Pixels Size模式写出来的,或者二者有同样的父类?

这三种模式的特点上面已经说过了,估计实际项目中要根据上线平台的屏幕分辨率多多尝试,看哪个效果更好就选哪个。

Match 当Match移到最左边时,仅宽度变化会影响画布缩放,当Match移到最右边时,仅高度会影响画布缩放。当Match移到中间某个点时,按二者的权重对画布进行缩放。
Reference Pixels Per Unit 如果精灵具有此“Pixels Per Unit”设置,则精灵中的每个像素将覆盖 UI 中的一个单位。

 

第三种模式:Constant Physical Size

这种模式看起来就感觉不常用,先不过多研究,等涉及到的时候再回过头来看看。

属性 功能
Physical Unit

用于指定位置和大小的物理单位。

centimeter 厘米

millimeter 毫米

inche 英寸

Point 点

pica 派卡

Fallback Screen DPI 在屏幕 DPI 未知时采用的 DPI。
Default Sprite DPI  用于精灵的每英寸像素,使其“Pixels Per Unit”设置与“Reference Pixels Per Unit”设置匹配。
Reference Pixels Per Unit 如果精灵具有此“Pixels Per Unit”设置,则其 DPI 将与“Default Sprite DPI”设置匹配。

作者:一白梦人

出处:https://www.cnblogs.com/ybmr/p/ugui_CanvasScaler.html

版权:本文版权归作者和博客园共有

转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任

posted @ 2021-02-02 17:48  一白梦人  阅读(501)  评论(0编辑  收藏  举报