unity屏幕适配

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity屏幕适配相关的知识,希望对你有一定的参考价值。

参考技术A

屏幕适配 :简单说,就是将UI以适当的尺寸显示在屏幕上的适当位置。
比如我们在手机上运行一个小游戏,打开它的菜单栏,一般都是如下画风

换一个手机,那就有可能是这个样子

现在市场上流行的像iPhone X的刘海屏,很多android手机的水滴屏,刘海屏,短刘海屏等等一系列手机,如果根据机型来适配,机型太多适配较复杂;我下面要介绍的是根据刘海屏、水滴屏等来适配,好在unity3d引擎在2017.2以上版本提供了屏幕安全区接口Screen.safeArea;
Screen.safeArea会返回移动平台安全区的Rect。例如,iPhoneX(2436x1125px)竖屏时,Screen.safeArea返回的值为Rect(0,132,2172,1125)。如图:

Screen.safeArea描述
返回屏幕的安全区域(以像素为单位)(只读)。

在某些显示器上,屏幕的某些区域可能对用户不可见。 这可能是由于显示器的形状并非矩形或是由过扫描(例如电视机屏幕)引起的。 请勿将用户界面元素放置到安全区域矩形以外的区域。 安全区域的最大大小是屏幕分辨率(以像素为单位),定义为 Rect(0, 0, Screen.width, Screen.height)。

设计思路顶部和底部设计到的UI界面尽量放到Screen.safeArea返回的Rect安全区域,如果不影响玩家点击交互的按钮可以不用放到安全区域,具体根据每个项目不同设计。为了不影响整体布局,安全区域以外可以用和背景颜色相近的图片完全填充。如下图:

很多Android上需要再Player Settings中勾选Render outside safe area,在安全区域以外渲染

unity — 屏幕适配(异形屏)

在Unity 2019.3 (beta)及其后版本可用 Device Simulator包,预设大部分机型,也可以自定义机型, 可以模拟机型的分辨率和刘海屏,非常方便做UI适配(现在刘海屏、水滴屏、挖空屏··· 各种屏,适配起来超级麻烦,Device Simulator功能,无需打包到真机就能看适配,方便!

打开方式:Package Manager包管理器下载,WIndow => General => Device Simulator

 

Screen.safeArea 会返回移动平台安全区的Rect。例如,iPhonex(2436x1125 px)横屏时,Screen.safeArea返回的值为Rect(132,63,2172,1062)。如图1-1:

                                      图1 - 1

适配情况处理:

1. UI是全屏背景,把背景放在安全区域外,其他UI组件放在安全区域内。

 2.适配需要靠边的UI ,把UI 拉长到屏幕外,达到适配效果,例如图1-2:返回按钮、玩家资产的背景图

3.无全面背景,四个角,或者上下,左中、右中,直接调整锚点进行适配。

                       图 1 - 2 

 

那么安全区域SafeArea的数值已知,以iphonex为例:那么safeArea的anchor  x轴最小值是:132 / 2436  =  0.05418,x轴最大值就是 1 - 0.05418。如图 1-3

                                                       图 1- 3

 

 

 

 

在iphonex模拟机上,左右两边有很多空白,经多次测试,用132的一半66除以屏幕宽即可,这样两边不会有太多的空白。把SafeAreaRect.cs挂在SafeArea物体上面就可以啦, 代码如下:

 1 using System;
 2 using UnityEngine;
 3 
 4 
 5 [DisallowMultipleComponent]//用于MonoBehaviour或其子类,不能重复添加这个类的组件,重复添加会弹出对话框
 6 [RequireComponent(typeof(RectTransform))]
 7 public class SafeAreaRect: MonoBehaviour
 8 {
 9     [NonSerialized]
10     private RectTransform _rect;
11     protected RectTransform rectTransform
12     {
13         get
14         {
15             if (_rect == null)
16                 _rect = GetComponent<RectTransform>();
17             return _rect;
18         }
19     }
20     
21     public static Rect cacheSafeArea = Rect.zero;
22     private void Awake()
23     {
24         if (cacheSafeArea == Rect.zero)
25             cacheSafeArea = GetSafeArea();
26 
27         ApplySafeArea(cacheSafeArea);
28     }
29 
30     private Rect __screenSafeArea = Rect.zero;
31     private void Update()
32     {
33         if (__screenSafeArea != Screen.safeArea)
34         {
35             cacheSafeArea = GetSafeArea();
36             ApplySafeArea(cacheSafeArea);
37         }      
38     }
39 
40     /// <summary>
41     /// 获取当前屏幕的参数
42     /// </summary>
43     private float[] GetCustomerSceneParam()
44     {
45         float[] sceneParam = new float[3];
46         sceneParam[0] = Screen.width;
47         sceneParam[1] = Screen.height;
48         sceneParam[2] = Screen.safeArea.x * 0.5f;
49         return sceneParam;
50     }
51 
52     private Rect GetSafeArea()
53     {
54         float x = 0, y = 0, w = 1, h = 1;
55         float[] param = GetCustomerSceneParam();//width、height、异性高度
56         var orientation = Screen.orientation;//获取屏幕方向
57         if (orientation == ScreenOrientation.Portrait || orientation == ScreenOrientation.PortraitUpsideDown)
58         {  //竖屏        
59             y = param[2] / param[0];
60             h = 1 - y;
61         }
62         else
63         {   //横屏        
64             x = param[2] / param[0];
65             w = 1 - x;
66         }
67         return new Rect(x, y, w, h);
68     }
69 
70     private void ApplySafeArea(Rect rect)
71     {
72 #if UNITY_EDITOR
73         __screenSafeArea = Screen.safeArea;//安全区域                
74 #endif        
75         rectTransform.anchorMin = rect.position;//rect.position的x、y轴最小值(对用的是rect(x,y))
76         rectTransform.anchorMax = rect.size;//rect.size也就是x、y轴最大值(对用的是rect(w,h))        
77     }
78 }

 

 

旋转问题 图1-4:

                         图1-4

 Default Orientation* Auto Roation:表示游戏支持自动旋转屏幕,但是前提是手机没有锁定屏幕旋转功能。

Landscape Right 和Landscape Left:表示手机屏幕只支持横屏两个方向的自动旋转。

Portrait 和 PortraitUpsideDown :表示竖屏、竖屏且上下颠倒

 

安卓横屏默认旋转为:Home键右手,导致如果右下角有操作,会不小心碰着返回按钮,影响玩家的体验。所以我们可以这么设置:

 

unity编辑器上系统设置:默认为 右横屏。

 

 通过代码,在Awake或者start中设置 横屏旋转:

1 void Start () 
2 {
3     //设置屏幕自动旋转, 并置支持的方向
4     Screen.orientation = ScreenOrientation.AutoRotation;
5     Screen.autorotateToLandscapeLeft = true;
6     Screen.autorotateToLandscapeRight = true;
7     Screen.autorotateToPortrait = false;
8     Screen.autorotateToPortraitUpsideDown = false;
9 }

以上是关于unity屏幕适配的主要内容,如果未能解决你的问题,请参考以下文章

unity — 屏幕适配(异形屏)

Unity3d--屏幕适配

Unity3D-UGUI篇Unity3D中UGUI的屏幕适配

Unity 3D 屏幕适配全方面解析!

unity ugui屏幕适配

Unity高级开发-项目与屏幕适配