Unity NGUI屏幕适配(转)

转自:https://blog.csdn.net/k46023/article/details/52837142

 

前段时间整理的一篇关于unity ui开发的文章,被推荐上了csdn首页,对于刚刚写文字的我来说,是莫大的鼓励,让我干劲十足,写出更多有质量的文字。

写在前面

屏幕适配是每个手机应用和游戏都会解决的问题,当然在开发的过程中会遇到各种各样的坑,这次,我们就来讨论一下unity项目中的屏幕适配吧!

目录

  1. 屏幕适配的分类
  2. 哪些内容需要适配
  3. unity中常见的适配方式
  4. 游戏内容适配
  5. NGUI的适配方案
  6. UGUI的适配方案

屏幕适配的分类

说到屏幕适配的分类啊,也许会有所疑问,屏幕适配还能分类?细致分析一下,可以分为两大类:分辨率适配和宽高比适配。

  1. 分辨率适配 
    首先得知道分辨率是什么?分辨率是屏幕显示图像的紧密度,是指显示器能显示的像素有多少。屏幕上的点、线、面都是由像素组成的,分辨率越高,同样大小的屏幕能显示的像素越多,画面就越精细。现在PC上分辨率大多是 1920 * 1080,我们看的视频很多高清版本就是 1080p 的。 
    既然分辨率是屏幕的一项指标,那么手机上当然也会用到,现在智能手机市场有那么多产品,有多个厂家生产,并且有多个价位,所以手机屏幕分辨率肯定各不相同(虽然屏幕分辨率一般比较固定的几个)。那么分辨率适配是每个应用、游戏都应该做的。

  2. 宽高比适配 
    这个很好理解,每个手机大小各不相同,宽高比也会有多种啦,适配宽高比当然也是必须要做的喽。

    当下移动设备主流分辨率及宽高比: 
    iOS设备的分辨率主要有: 
    Unity NGUI屏幕适配(转)_第1张图片

    Android设备的分辨率则相对纷杂,主流的分辨率有: 
    Unity NGUI屏幕适配(转)_第2张图片

哪些内容需要适配

  1. User Interface 
    游戏UI需要适配,这是无所质疑的,包括一般的手机应用程序,都需要这个步骤。如果再细分一下,还分为位置适配和大小适配

    位置适配:分辨率会影响UI在屏幕中显示的位置,比如在800 * 600分辨率的屏幕上,button1在正中央位置,坐标为(400, 300),但是如果放在1366 * 768分辨率屏幕上位置就会靠左边一些,这样会严重影响UI布局的美观。

    大小适配:同样的例子,在800 * 600分辨率的屏幕上,button1的大小为50*20像素,但是到了分辨率高的屏幕上,button1就变得很小了,影响美观,影响用户正常使用。

    Unity NGUI屏幕适配(转)_第3张图片

  2. 游戏内容 
    一般的应用开发,用户看到的只有UI,但在游戏中,除了UI,还有游戏内容。而游戏内容是什么呢?

    举个例子: 
    比如在2D游戏中,除了那些可以交互的按钮滚动,在二维场景中的背景、物件、NPC等,都属于游戏内容。在进行宽高比适配的时候,难免会按照宽度或高度做一些裁剪,如果不进行处理,有些游戏内容就会看不到。 
    在3D游戏中,场景的大小是固定的,当相机照射的宽高比因为适配屏幕宽高比变化时,就可能“穿帮”,很有可能看到黑边。

    在unity中不管2D游戏还是3D游戏,分辨率大小不会影响游戏内容显示,屏幕宽高比会影响游戏内容显示。

    注意:在unity编辑器中,game视图是默认的视口,并且编辑器下改变游戏宽高比,unity会自动把相机宽高比调整到适配的宽高比。

unity中常见的适配方式

  1. Camera组件 
    Projection:投影类型 
    Prespective为透视投影

    Unity NGUI屏幕适配(转)_第4张图片

    Field of View:相机的张角,它决定相机照射的范围。 
    Clipping Planes:近裁剪面和远裁剪面 
    Viewport Rect:视口大小,取值为0 ~ 1之间

    Orthographic为平行投影

    Unity NGUI屏幕适配(转)_第5张图片

    与透视投影不同的是size属性,它用来调整摄像机的大小 
    orthographicSize:等于相机高度的一半

    注意一下,unity中的单位和像素之间有一个转换关系,叫做Pixels To Units 
    Unity NGUI屏幕适配(转)_第6张图片

    默认为100,unity中一个单位表示图片的100个像素。如果游戏屏幕高为800像素,那么换算后高度为 800 / 100 / 2 = 4。

    unity没有直接设置摄像机宽度的属性,也没有获取摄像机宽度的接口,但可以通过高度和宽高比计算出来。那么计算宽度如下:

    cameraWidth = camera.orthographicSize * 2 * camera.aspect

    换算成像素:cameraWidth * 100

    cameraHeight = camera.orthographicSize * 2

    换算成像素:cameraHeight * 100

    相机的宽高比是unity自动设置为当前屏幕宽高比的,所以camera.aspect不需要自己设置。

  2. 缩放 
    在Transform组件上,可以设置控制物体每个方向上的缩放比例。 
    这里写图片描述

  3. 锚点(相对位置) 
    目前NGUI,UGUI都有类似的功能,稍后再讨论。

游戏内容适配

游戏内容可以分为两类 
有效内容:游戏中一定需要显示在屏幕上的内容 
实际内容:包括有效内容和为了适配、或其它目的增加的内容。

  1. 3D游戏中把要么场景做得比正常显示时更大一些;要么显示天空盒子。

  2. 2D游戏中也是把背景做得大一些,尽可能让游戏不出现黑边。 
    我们的开发一般都会选择在一个固定的设计分辨率上进行,比如常用的iOS竖屏游戏设计分辨率640*960,我们就以这个设计分辨率为例。通常情况下,设计分辨率尺寸就是我们游戏有效内容的尺寸。 
    orthographicSize设置为4.8,就可以让游戏内容铺满屏幕

    这里有一篇文章,里面详细讲了unity 2D游戏的屏幕适配。

NGUI适配方案

  1. UIRoot 
    NGUI中每一个UI都是以UIRoot作为根节点,该组件完成了NGUI大体上的适配功能。 
    UIRoot的几种缩放方式: 
    Unity NGUI屏幕适配(转)_第7张图片

    Flexible:

    在该模式下,下面的UI都是以像素为基础,100像素的物体无论在多少分辨率上都是100像素,这就意味着,100像素在分辨率低的屏幕上可能显示正常,但是在高分辨率上就会显得很小。

    在该模式下,UIRoot的属性如下: 
    Unity NGUI屏幕适配(转)_第8张图片

    Minimum Height:设置为725时,当屏幕高度小于725时,在该屏幕上显示的样子和开发时一致。 
    Maximum Height:设置为1024时,当屏幕高度大于1024时,在该屏幕上显示的样子和开发时一致。

    Shrink Portrait UI:当是竖屏状态时,按宽度来适配。 
    Adjust by DPI:使用dpi做适配计算。

    补充一下一些关于屏幕的基本概念

    dip:设备无关像素 
    dp:就是dip 
    px:像素 
    dpi:像素密度,单位面积上有多少个像素点 
    分辨率:宽高两个方向上的像素点数,如800*600 
    屏幕尺寸:屏幕对角线长度 
    屏幕比例:宽高比

    详细的转换关系,去这里看看。

    开发时的布局: 
    Unity NGUI屏幕适配(转)_第9张图片

    改变Game视图大小: 
    Unity NGUI屏幕适配(转)_第10张图片

    改变Game视图大小,高度大于725,小于1024,(按刚刚的截图中设置的值测试的): 
    Unity NGUI屏幕适配(转)_第11张图片

    在高度在Minimum和Maximum之间时,UIRoot就不会对下面的UI缩放了,开发时有多少像素在高分辨下也只有那么点像素,所以看起来就变小了。

    这个Minimum和Maximum Height用于你对实际的屏幕尺寸进行限制,如果实际的屏幕尺寸小于Minimum,那么就相当于设置了“Constrained”模式、Manual Height值设为Minimum的时候一样,同理,如果屏幕尺寸超过了Maximum,那也相当于设置了“Constrained”模式、Manual Height值设为Maximum的时候一样。

    以上是在Flexible模式的关于分辨率的适配,还有一个是宽高比适配,分两种情况:

    当高大于宽的是,也就是竖屏状态时 
    Unity NGUI屏幕适配(转)_第12张图片

    两边被截了 
    Unity NGUI屏幕适配(转)_第13张图片

    只需要勾上Shrink Portrait UI,就能按照宽度来适配了(因为默认横屏状态,并且默认按高度适配,所以在看这段源码的时候,它里面的计算是宽高颠倒的): 
    Unity NGUI屏幕适配(转)_第14张图片

    当宽大于高时,也就是横屏状态时:就需要自己来根据宽度来调整缩放。

    • 动态的改变适配的高度

      public class NewBehaviourScript : MonoBehaviour {
      
       public int ManualWidth = 1280;
       public int ManualHeight = 720;
      
      void Awake () {
          UIRoot uiRoot = gameObject.GetComponent();
      
           if (uiRoot != null)
          {
              if (System.Convert.ToSingle(Screen.height) / Screen.width > System.Convert.ToSingle(ManualHeight) / ManualWidth)
                  uiRoot.minimumHeight = Mathf.RoundToInt(System.Convert.ToSingle(ManualWidth) / Screen.width * Screen.height);
              else
                  uiRoot.minimumHeight = ManualHeight;
          }
      }
      }
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
    • 利用相机的camera.orthographicSize 
      需要知道orthographicSize表示的是相机高度的一半,前面已经讲清楚了。我在16 : 9屏幕下开发,并且设置camera.orthographicSize为1,把Minimum和Maximum设置为相同 
      Unity NGUI屏幕适配(转)_第15张图片

    ,然后把下面脚本挂在UI相机上:

    public class NewBehaviourScript : MonoBehaviour {
    
    void Awake ()
     {
         camera.orthographicSize *= 16.0f / 9 / ((float)Screen.width / Screen.height);
    }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    16:9屏幕上正常: 

    不加上述脚本,在5:4屏幕上,两边被裁剪了: 
    Unity NGUI屏幕适配(转)_第16张图片

    加上上述脚本,在5:4屏幕上就正常了,按照宽度适配: 
    Unity NGUI屏幕适配(转)_第17张图片

    Constrained:

    该模式下,屏幕按照尺寸比例来适配,不管实际屏幕有多大,NGUI都会通过合适的缩放来适配屏幕。这样在高分辨率上显示的UI就会被放大,有可能会模糊。 
    这里写图片描述

    Content Width:按照该宽度值适配屏幕 
    Content Height:按照该高度值适配屏幕

    Fit选项表示已哪个值做适配。这两个值可以认为是事先设定好的屏幕初始大小和比例。源码中Fit选项的枚举值:

    public enum Constraint
    {
    Fit,
    Fill,
    FitWidth,
    FitHeight,
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 如果Fit都没勾选(Constraint.Fill) 
      当适配宽高比小于实际宽高比时,就会按照宽度适配,反之按照高度适配。该情况下可以保证显示结果永远没有黑边,但上下或者左右两边可能会被裁剪。

    • 如果勾选了Width(Constraint.FitWidth) 
      那么就会在屏幕比例发生变化时,按照宽度来适配。例如开发时用16:9屏幕,运行在5:4屏幕上,宽度适配,计算公式为 activeHeight = manualWidth / (screen.x / screen.y),16 / ( 5 / 4 ) = 12.8 > 9,这样显示宽度就全部显示进来了,但是高度上就会出现黑边,所以这种情况下要想办法解决黑边问题。

    • 如果勾选了Height(Constraint.FitHeight) 
      那么就会在屏幕比例发生变化时,按照宽度来适配。activeWidth = manualHeight * (screen.x / screen.y),9 * ( 5 / 4 ) = 11.25 < 16,这样高度全部显示进来,但在宽度上两边被裁剪掉了,显然这样更不合适了。

    • 如果两个都勾选了(Constraint.Fit) 
      当适配宽高比大于实际宽高比时,就会按照宽度适配,反之按照高度适配。该情况下可以保证显示开发时能见到的所有内容,但是可能上下或左右会出现黑边。

    下面是UIRoot.cs源码: 
    Unity NGUI屏幕适配(转)_第18张图片

    可以清楚的看到NGUI是怎么利用这些值进行计算高度的。

    Constrained On Mobiles

    前两种模式的组合,在PC和Mac等桌面设备上用Flexible模式, 在移动设备上Constrained模式。

  2. UIAnchor or UIStretch 
    作为NGUI中一个组件,但之前做的项目里面好像怎么用,可以把它看做对一个UI树中的局部进行控制。它们在处理细节上很相似,都是先计算参照对象(这个参照对象由Insprector的Container指定,如果没有选择,就是Camera)的大小Rect,然后根据参数UIAnchor(Side,relativeOffset,pixelOffset),UIStretch(Style,relativeSize,initialSize,borderPadding)进行调整,最后设置对应的属性,只不过UIAnchor设置的是transform.position,UIStretch设置的是(width,height)或clipRange等。

    UIAnchor组件的视图: 
    Unity NGUI屏幕适配(转)_第19张图片

    Container:指定Anchor的参照点,如果没有选择,则以Camera的pixelRect的区域为参照面 。 
    Side:锚点位置,有八个位置可选。 
    Relative Offset:相对于Camera,或Container的百分比偏移 。 
    Pixel Offset:像素的偏移。

    UIStretch组件的视图: 
    Unity NGUI屏幕适配(转)_第20张图片

    大致和UIAnchor差不多,Style属性有些改动如下

    Horizontal:横向拉伸。 
    Vertical:纵向拉伸。 
    Both:双向拉伸,但xy方向上的拉伸比例不同。 
    BasedOnHeight:双向拉伸,但xy方向上的拉伸比例相同,且比例基于height。 
    FillKeepingRatio:双向拉伸,但xy方向上的拉伸比例相同,比例基于较大者。 
    FitInternalKeepingRatio:双向拉伸,但xy方向上的比例相同,比例基于较小者。

    具体的可以自己研究一下,但是不建议用这个两货,折腾了一下感觉太麻烦,而且根本没必要啊,因为UIRoot已经做了大部分的适配了,那些局部细节上的调整完全可以用UIRect所管理的Anchor来实现,它不是单独的组件,比这两简单多了,下面就来聊聊它。

  3. UIRect的Anchor 
    首先得了解一些UIRect,这里不详细聊它,后面会整理一篇分析NGUI底层的文章,里面有详细说它。简单介绍一下,从NGUI控件的继承结构上,UIRect是所有weight和panel的基类,管理着rect和anchor,计算、生成,是一个抽象类。

    拿UISprite举例: 
    Unity NGUI屏幕适配(转)_第21张图片

    Type:三种类型,使用锚点、基本控制、完全控制。 
    Execute:设置在什么时候执行锚点适配。 
    Target:参考物体。 
    Left、Right、Bottom、Top:该控件上下左右边。

    比如,你想某个按钮在任何尺寸屏幕上都停留在屏幕上的左边,可以如下:

    16:9屏幕上 
    Unity NGUI屏幕适配(转)_第22张图片

    锚点设置如下:UISprite的左右边界都参考target的左边 
    Unity NGUI屏幕适配(转)_第23张图片

    然后5:4屏幕上,UISprite依然在屏幕的左边了 
    Unity NGUI屏幕适配(转)_第24张图片

    当然其它的weight都可以设置锚点,可以这么说,凡事继承自UIRect的组件都可以使用该锚点。

UGUI适配方案

终于把NGUI适配说完了,对于UGUI目前没有深入了解,在场景视图中可以拖拽锚点,设置锚点区域,感觉挺简单的,粗略做个笔记。

  1. Canvas Scaler:画布比例缩放,从整体上对UI进行适配控制,和UIRoot有异曲同工之妙,很多参数名字不一样,但意思一样。

    ConstantPixelSize:按像素适配 
    这里写图片描述

    Constant Pixel Size:保持UI元素大小不变,无论屏幕尺寸如何变化,所占像素不变。 
    Scale Factor:保持大小的比例 。原图100x100 原始大小1=100x100 原来的2倍大 2=200x200 
    Reference Pixels Per Unity: 100 Unity里的1单位大小代表100像素

    ScaleWithScreenSize:按比例适配 
    Unity NGUI屏幕适配(转)_第25张图片

    Scale With Screen Size:UI元素大小跟随屏幕分辨率的大小变化而变化。 
    Reference Resolution:参考分辨率。 
    Screen Match Mode: 
    Match Width Or Height:根据参考分辨率的高或宽,来缩放UI元素。 
    Expland:分辨率设置不会小于Canvas设置的分辨率。 
    Shrink:分辨率不会大于Canvas设置的分辨率。

    Constant Physical Size:按屏幕物理大小适配 
    Unity NGUI屏幕适配(转)_第26张图片

    根据屏幕的PPI信息和ConstantPhysicalSize本身的配置信息,得出一个“合适”的scaleFactor,以达到UI在不同PPI设备上的最终大小都是一致的。

  2. 锚点 
    UGUI中锚点有多种“形态”,当锚点是一个点时,表示该UI大小不变,位置会随参考点改变。当锚点是一个矩形区域时,UI的大小就会随该参考区域改变,当然非常灵活,锚点矩形的大小可以随意设置,甚至可以在某个方向长度为0。

写在最后

以上就是屏幕适配的所有内容,主要介绍了屏幕适配的分类:分辨率适配和宽高比适配,按内容又分为游戏UI适配和游戏内容适配,并给出一些适配方法。然后重点讲了NGUI的适配方法,简单介绍了UGUI,总的来说UGUI和NGUI适配的方案有很多相似的地方,适配的大致方向就是按像素、按比例缩放对全局适配,用锚点来做精细的控制。对UGUI现在不是很熟,所以写的很简单,以后找时间在详细研究一下,再整理出来。

你可能感兴趣的:(Unity NGUI屏幕适配(转))