浅谈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
  • 10
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Unity UI框架是一个用于创建用户界面的工具集,它提供了许多组件和功能,以帮助开发人员快速构建漂亮的UI。下面是一个简单的Unity UI框架,包括以下组件: 1. Canvas:用于容纳所有UI元素的容器。 2. Panels:用于将UI元素分组并对它们进行布局的容器。 3. Text:用于显示文本的组件。 4. Image:用于显示图像的组件。 5. Button:用于创建可点击的按钮。 在这个框架中,我们将使用UnityUI系统来创建所有UI元素。我们将首先创建一个Canvas对象,并将其作为根UI元素。然后,我们可以在Canvas上创建任意数量的面板,并将它们用于分组UI元素。每个面板都可以拥有自己的布局,并且可以包含任意数量的UI元素。 在面板中,我们可以添加文本、图像和按钮等UI元素。文本组件用于显示文本,我们可以设置字体、字号、颜色等属性。图像组件用于显示图像,我们可以设置图像的纹理、大小、位置等属性。按钮组件用于创建可点击的按钮,我们可以在按钮上添加事件处理程序,以便在点击按钮时执行某些操作。 通过组合这些UI组件,我们可以创建各种各样的用户界面,例如菜单、游戏界面、设置界面等。我们可以使用代码来动态创建UI元素,也可以使用Unity的可视化编辑器来创建和布局UI元素。 总的来说,Unity UI框架是一个非常强大和灵活的工具,可以帮助开发人员轻松创建漂亮的用户界面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值