0


浅谈Unity UI适配(一)

0 楔子

最近想换工作,在准备面试,突然想起了三年前一个没有答上来的问题,就是Unity的UI有几种适配模式,都是什么意思。当时支支吾吾半天没讲出来,今天必须搞懂它。

1 Canvas组件

我们知道,Unity里的UI元素都要绘制在Canvas上,那么就先来看Canvas是个什么东西:

如上图所示,Canvas 渲染模式有三种:Screen Space-Overlay、Screen Space-Camera、World Space。下面就分别进行进行解析:

1.1 World Space —— 世界模式


属性****功能Event Camera 响应事件的相机Sorting Layer画布的深度,指定了相机的渲染顺序Order in Layer值越大,该UI越显示在前面Addtional Shader Channels附加着色通道,决定Shader可以读取哪些相关数据,比如 法线、 切线 等数据。
在世界空间渲染通常用于显示人物头顶的血条,NPC头上的名字等等。这种情况下,UI位于世界坐标系中,我习惯称它为3DUI,3DUI是游戏中负责渲染3d模型的相机来渲染的,如果要做适配,也是针对3d相机适配,通常都是调节下fov,来保证不同长宽比的屏幕看到的画面大致一样。并不需要针对3dui做适配。

1.2 Screen Space-Overlay —— 屏幕空间覆盖模式


属性****功能Pixel Perfect使UI元素像素对应,效果就是边缘清晰不模糊Sort Order多个Canvas时,数值越大越后渲染。值大的画布,会挡住值小的Target Display目标显示器,如果有多个屏幕的话可以选择Addtional Shader Channels附加着色通道,决定Shader可以读取哪些相关数据,比如 法线、 切线 等数据。
这个屏幕空间覆盖模式渲染模式,就是表示不管有没有相机去渲染场景,Canvas下的所有UI永远位于屏幕的前面,覆盖掉渲染场景显示的元素。

1.3 Screen Space-Camera —— 相机模式


属性****功能Pixel Perfect使UI元素像素对应,效果就是边缘清晰不模糊Render Camera渲染的相机Sort Order多个Canvas时,数值越大越后渲染。值大的画布,会挡住值小的Order In LayerCanvas属于的排序层,在 Edit->Project Setting->Tags and Layers->Sorting Layers 进行新增,越下方的层显示越前面Plane Distance Canvas与相机之间的距离
这种渲染模式 适用于场景模型太多太大,在调整UI的时候挡住UI,让UI和渲染的相机移动到比较远的位置,就可以避免遮挡。并且Canvas 和 摄像机之间有一定的距离 , 可以在摄像机和 Canvas之间放置一些模型或粒子特效。

Screen Space-Camera和Overlay很相似,不同点就在于,Overlay只会根据屏幕的尺寸、分辨率和CanvasScaler的设置,来自动调节画布长宽和缩放。而使用Camera的画布除了受上述因素影响,还会额外受到Camera参数设置影响。

Overlay的性能也会稍微好点,使用Overlay时,UI元素会简单粗暴的绘制在最上层,Unity不需要考虑剔除和排序。但这点性能损耗也无伤大雅,大家知道就好。

2 Canvas Scaler

我们可以观察到,Canvas物体上面,除了Canvas组件,还有一个组件叫做Canvas Scaler,这个组件就是专门来调节Canvas大小的,以达到UI适配的目的。如下图所示:

Canvas 缩放模式有三种:Constant Pixer Size、Scale With Screen Size、Constant Physical Size

下面就分别进行进行解析:

2.1 Constant Pixer Size —— 恒定像素

属性****功能Scale Factor 缩放因子Reference Pixels Per Uit
单位面积像素数量,默认100

Scale Factor参数
首先,来看官方代码对于这个参数的设置:

protected void SetScaleFactor(float scaleFactor)
{
    if (scaleFactor == m_PrevScaleFactor)
        return;
 
    m_Canvas.scaleFactor = scaleFactor;
    m_PrevScaleFactor = scaleFactor;
}

用代码可以看出来,Canvas Scaler 透过设定Canvas下的Scale Factor参数来缩放所有在此Canvas下的UI元素的大小,下面就举个例子说明一下。
例子:
当前分辨率为1920 X 1080,将Scale Factor设为1:

Canvas的长宽等于整成的屏幕的长宽(1920 X 1080),缩放是1倍。

将ScaleFactor设置为2:

Canvas的长宽变成了缩减了一半,缩放变成了2倍。

而图片大小也变成了原来的2倍大。

假如我们维持 ScaleFactor 不变,使用不同的分辨率进行游戏,又会怎样呢?

下面是ScaleFactor为1时,分辨率为1280x720的图片大小:

我们将分辨率调成100x100:

可以观察到,图片本身大小没有变化。但是已经充满了整个屏幕。也就是说,在这种适配模式下,如果我们想将图片等比缩小,就需要自己手动调节ScaleFactor。

Reference Pixels Per Unit参数

这里,我们详细的介绍一下Constant Pixer Size模式下的Reference Pixels Per Unit属性跟图片的Pixels Per Unit的关系。

举个例子
导入项目一张图片,将图片的Pixels Per Unit设置为100:

场景中有一个标准大小的Cube和一个标准大小的Sprite,两者的缩放比例都为1,大小一致:

当图片的Pixels Per Unit为100,每单位由100Pixels组成,那么这个Sprite在世界坐标就是

图片大小 = (100/100) =1 Unit

然后,将图片的Pixels Per Unit设置为10:

图片大小 = (100/10) =10 Unit

结论:

  • Unity中一单位等于 100 Pixels
  • 公式:Sprite的大小 = 原图大小(Pixels)/ Pixels Per Unit

让我们回到 Reference Pixels Per Unit,官方解释是,如果图片档有设定Pixels Per Unit,则会将Sprite 的 1 pixel 转换成 UI 中的 1 pixel,让我们来看一下官方代码:

public float pixelsPerUnit
{
    get
    {
        float spritePixelsPerUnit = 100;
        if (sprite)
            spritePixelsPerUnit = sprite.pixelsPerUnit;
 
        float referencePixelsPerUnit = 100;
        if (canvas)
            referencePixelsPerUnit = canvas.referencePixelsPerUnit;
 
        return spritePixelsPerUnit / referencePixelsPerUnit;
    }
}
public override void SetNativeSize()
{
    if (overrideSprite != null)
    {
        float w = overrideSprite.rect.width / pixelsPerUnit;
        float h = overrideSprite.rect.height / pixelsPerUnit;
        rectTransform.anchorMax = rectTransform.anchorMin;
        rectTransform.sizeDelta = new Vector2(w, h);
        SetAllDirty();
    }
}

上面的代码,可以看出 Image 是通过 spritePixelsPerUnit / referencePixelsPerUnit 方式算出新的 pixelsPerUnit大小。

在设定 Image 图片大小时,是把 宽高 / Pixels Per Unit。

实测一下,建立一个Canvas参数如下:

Canvas下面新建一个Image,参数如下:

通过修改Canvas Scaler的Reference Pixels Per Unit参数 与 图片的Pixels Per Unit参数,来做4组测试,然后来看图片的不同变化:

■ 上表可以看出当数值改变时,图片预设大小也会改变

■ 由此可以推导出公式

UI大小 = 原图大小(Pixels) / Pixels Per Unit * Reference Pixels Per Unit
标签: unity ui

本文转载自: https://blog.csdn.net/qq_17758883/article/details/125883295
版权归原作者 萌新求带 所有, 如有侵权,请联系我们删除。

“浅谈Unity UI适配(一)”的评论:

还没有评论