ngui屏幕自适应(三合一)

来源:互联网 发布:电脑访问不了淘宝网 编辑:程序博客网 时间:2024/04/29 21:02



部分内容有重复,未整理。


【一】

转自:http://tieba.baidu.com/p/2450692089


很多做移动终端开发的童鞋都可能遇到一个问题,就是如何自适应
其实NGUI已经能帮我们实现,下面就告诉大家怎么整这个自适应。
1,create a new ui 
2,uiroot下添加uipanel(script)
3,camera的size设置为美术给你的图的size(比如美术给你的是960*640,size=960),
4,panel添加uistretch(script),其中的style设置为both,并将relative size的x和y都设为960(同上的道理,明白?)
5,再在panel下add一个sprite(最好是960*640)的背景图,其中transform的s一定注意要是1,不能再放大了。
以上就ok了
注明下:
uistretch的缩放NGUI提供了5种,

public enum Style
{
None,
Horizontal,
Vertical,
Both,
BasedOnHeight,
BasedOnWidth,
}
我自己加了一种BasedOnWidth,其实代码很简单,如下:

else if(style == Style.BasedOnWidth)
{
localScale.x = relativeSize.x * screenWidth;
localScale.y = relativeSize.y * screenWidth;
localScale.z = localScale.x;
}
是不是很简单?
大功告成,希望对大家有帮助!
补充下,还有种方法比上面要好点。
camera的size设置为1
uistretch的relative的size设置为x=1/960f,y=1/960f
这样你的资源的就不用缩放了
自己实践补充
if (style == Style.BasedOnHeight)
{
//****** NGUI默认处理方式 **********
//localScale.x = relativeSize.x * rectHeight;
//localScale.y = relativeSize.y * rectHeight;
//****** 自己稍做修改结果 发现适用范围更广泛**********
localScale.x = relativeSize.x * rectHeight-relativeSize.x * rectHeight*0.25f;
localScale.y = relativeSize.y * rectHeight-relativeSize.x * rectHeight*0.25f;
}





【二】NGUI屏幕自适应

http://blog.csdn.net/xinshou_jiaoming/article/details/8087529

屏幕自适应

NGUI可以比较方便的实现屏幕自适应,但是它的官方教程里面针对这个问题没有详细的教程,所以可能在实现的时候会走比较多的弯路。以下是我在开发过程中找到的一个比较方便的实现方法。

主要组件

1. UIAnchor

这个是用来确定控件在屏幕中的位置,另外有一篇教程专门讲它的功能,所有不会再赘述

2. UIStretch

这个是用来做缩放的组件。老版本的NGUI是集成在UIAnchor上的。新版本的UIStretch提供了4种缩放方式:

Horizontal:只缩放水平方向

Vertical:只缩放垂直方向

Bose:缩放两个方向

BasedOnHeight:基于高度等比缩放

然后基于这些我自己实现了一个

BasedOnWidth:基于宽度等比缩放

代码如下:

[csharp] view plaincopy
  1. else if(style == Style.BasedOnWidth)  
  2. {  
  3.     localScale.x = relativeSize.x * screenWidth;  
  4.     localScale.y = relativeSize.y * screenWidth;  
  5.     localScale.z = localScale.x;  
  6. }  

这段代码添加在Update方法里面。为了能将UIStretch挂在UIPanel上面不出问题,所有将Z轴也缩放了。

自适应流程

1. 创建一个新的UI,将Anchor里面的UIAnchor调整的合适的位置,注意最好将Anchor设置为Bottom。

2. 将Camera的Size调节到默认屏幕大小。比如UI是以960*640分辨率制作的,那么将Camera的Size调整到960。

3. 在Panel上面添加一个UIStretch,模式选择BasedOnWidth。完成之后你可以看到你的Panel的Scale被修改到了当前屏幕的X方向分辨率大小。

4. 将UI控件添加到Panel上,调整位置,在Panel下的所有控件都会以X方向为标准做等比缩放来适应屏幕大小。

5. 添加一张作为背景的图,将UISprite的anchor设置为Bottom,添加之后你可以看到这个sprite可以在不同的分辨率下自适应了。

6. 以上一步添加的背景图作为参照物来摆放页面上的控件,这样不仅仅是大小,位置也同样会按照相同的模式进行等比缩放

7. 可以在第3步创建的Panel下面添加子Panel,子Panel不需要UIStretch(一般用来做Draggable Panel,否则没必要,会增加额外的Draw Call)

8. 如果某一些控件需要定位在屏幕上下左右中的某一角,可以单独给他添加一个UIAnchor,这个时候UIStretch只会缩放这个控件的大小,它的位置由他自己的UIAnchor控制了




【三】nguI 屏幕自适应

http://blog.csdn.net/luyuncsd123/article/details/15034015

一、当下移动设备的主流分辨率
1.1 iOS设备的分辨率主要有:

宽  高 宽高比
960 640 1.5
1136 640 1.775
1024 768 1.3333
2048 1536 1.3333

Android设备的分辨率则相对纷杂,主流的分辨率有:
宽 高 宽高比
800 480 1.6667
854 480 1.7792
1280 720 1.7778
960 540 1.7778
1280 800 1.6
960 640 1.5
1184 720 1.6444
1920 1080 1.7778


二、NGUI默认的多分辨率适配原则
NGUI本身按照“高度适配”的原则进行多分辨率下的UI适配,其默认的高度通过 UIRoot.manualHeight 设置。再配合使用   UIAnchor 便可实现一定程度的多分辨率适配。

其中,在Unity Editor下按照 UIRoot.manualHeight   设定的高度,编辑UI页面。这样,当UI页面在目标设备上显示时,NGUI按照目标设备的高度(targetHeight)来调整UIRoot节点的scale,以使整个UI页面适应目标设备的高度。比如manualHeight=400,而targetHeight=800,那么UIRoot的scale将被乘以2。所以,当目标设备的宽高比与所编辑页面的宽高比一致时,整个UI将完美显示;当目标设备宽高比小于所编辑的宽高比时,页面宽度将大于设备宽度,使得多出的部分无法显示;而当目标设备宽高比大于所编辑宽高比时,页面宽度小于设备宽度,设备两边将出现黑边。

而UIAnchor则是将整个页面分为TopLeft/Top/TopRight/Left/Center/Right/BottomLeft/Bottom/BottomRight九个区域,挂载了UIAnchor组件的节点都将按照设置自动停靠到相应的区域中。有了UIAnchor,上面的两个问题将被一定程度的解决:当目标设备宽高比小于编辑的宽高比时,由于UIAnchor的自动停靠功能,UI不会被裁切掉,但UI之间的左右间距将相应变小,便有可能出现UI重叠的问题;当目标设备宽高比大于所编辑宽高比时,UI之间的左右间距将变大,好在这样起码不会有UI被裁切或重叠。

看似我们只需要解决UI重叠的问题就搞定了。不过让我们再仔细想一下,一张铺满整个屏幕的UISprite不管是否使用UIAnchor,在目标设备宽高比更小时,sprite都会在横向上被裁切,而将目标设备宽高比更大时,sprite都不能铺满整个屏幕。

问题出来了:
1. 当目标设备宽高比更小时的UI重叠问题
2. 当目标设备宽高比更小时,全屏sprite被裁切问题
3. 当目标设备宽高比更大时,全屏sprite不能铺满整个屏幕的问题


三、解决问题
首先定义几个变量:
standard_width  编辑页面的原始宽度
standard_height  编辑页面的原始高度
device_width    目标设备的宽度
device_height    目标设备的高度
standard_aspect  编辑页面的宽高比
device_aspect    目标设备的宽高比

1. 目标设备宽高比更小时的UI重叠问题
  当device_aspect小于standard_aspect时,UIRoot根据device_height调整其scale大小,因而使得设备宽度不足以显示整个页面。我们调整Camera.orthographicSize(仅适用2D   GUI),以足够显示页面的宽度。令
  Camera.orthographicSize = standard_aspect / device_aspect;
即,改变了NGUI原有的“高度适配”原则,转为“宽度适配”,使得整个页面都得以显示,而由于UIAnchor的存在,UI的左右间距保持不变,但上下间距会变大。
该方法可以实现为一个MonoBehaviour脚本(UICameraAdjustor.cs),挂载到UICamera同一个节点上,代码如下:


1 using UnityEngine;
2 using System.Collections;

4 /// <summary>
5 /// 根据设备的宽高比,调整camera.orthographicSize.   以保证UI在不同分辨率(宽高比)下的自适应
6 /// 须与UIAnchor配合使用
7 /// 将该脚本添加到UICamera同一节点上
8 /// </summary>

10 [RequireComponent(typeof(UICamera))]
11 public class UICameraAdjustor : MonoBehaviour
12 {
13     float standard_width = 1024f;
14     float standard_height = 600f;
15     float device_width = 0f;
16     float device_height = 0f;
17 
18     void Awake()
19     {
20         device_width = Screen.width;
21         device_height = Screen.height;
22 
23         SetCameraSize();
24     }
25 
26     private void SetCameraSize()
27     {
28         float adjustor = 0f;
29         float standard_aspect = standard_width /   standard_height;
30         float device_aspect = device_width /   device_height;
31 
32         if (device_aspect <   standard_aspect)
33         {
34             adjustor = standard_aspect /   device_aspect;
35             camera.orthographicSize =   adjustor;
36         }
37     }
38 }



总之,在使用该方法后,当device_aspect大于standard_aspect时,UI按照高度适配原则,UI的上下间距不变,左右间距变大;当device_aspect小于standard_aspect时,UI按照宽度适配原则,UI的左右间距不变,上下间距变大。

2. 目标设备宽高比更小时,全屏sprite被裁切问题
  全屏背景的sprite被裁切可能在很多情况下不会成为什么问题,但在我们使用了解决问题1中的方法后,这里的“被裁切问题”就变为了同问题3类似的“不能铺满整个屏幕问题”。解决方法是放大sprite   scale:
  sprite.transform.localScale *= ( standard_aspect / device_aspect   );
这样会使得sprite在横向上被裁切,宽高比不同必然的结果... 当然也可以选择只调整高度或宽度,只要能接受变形...

3. 目标设备宽高比更大时,全屏sprite不能铺满整个屏幕的问题
  同问题2,解决方法同样是放大sprite scale:
  sprite.transform.localScale *= ( device_aspect / standard_aspect   );
这样会使得sprite在纵向上被裁切。

问题2和3的解决方法相应脚本(UIBackgroundAjustor.cs)会在文章后面给出。
该脚本须挂载到sprite同一节点上,配合UIAnchor使用,可以选择是裁切方向。如UIAnchor停靠方式使用center,则sprite会被左右两边或上下裁切,若使用Top,则会左右裁切或下边裁切。
总之,全屏sprite会始终铺满整个屏幕,不会出现黑边。当device_aspect大于standard_aspect时,全屏sprite按照宽度适配,纵向裁切;当device_aspect小于standard_aspect时,按照高度适配,横向裁切。

四、优化
1. UI页面的制作尺寸按 1024 X 600
  前面讲到主流分辨率的情况,其平均宽高比(除ipad2/3/4以外)大概为1.7,与主流的宽高比都不会偏差很大。即,在使用上面的多分辨率解决方法时,UI不会在纵向或横向上的间距过大,显得特别离谱。按照此宽高比,我们选择1024x600的尺寸来制作UI,并严格要求UI制作时,页面分为TopLeft/Top/TopRight/Left/Center/Right/BottomLeft/Bottom/BottomRight九个区域,以便挂载UIAnchor。

2. 全屏背景的制作按 1024 X 768
  如果全屏背景图也按1024 x   600制作,在ipad2/3/4上就会有较大程度的放大。同时考虑到NGUI的打包atlas,使用2的幂次尺寸,高度600和768都将占用1024x1024的atlas。所以全屏背景在制作时,高度上做出一定的冗余尺寸,以使宽高比小于1.7时,高度上放大系数不会太大,避免图片严重失真。
  加入冗余尺寸后的脚本(UIBackgroundAjustor.cs)如下:

1 using UnityEngine;
2 using System.Collections;

4 /// <summary>
5 /// 根据设备的宽高比,调整UISprite scale, 以保证全屏的背景图在不同分辨率(宽高比)下的自适应
6 /// 将该脚本添加到UISprite同一节点上
7 /// 须与UICameraAdjustor脚本配合使用
8 /// </summary>

10 [RequireComponent(typeof(UISprite))]
11 public class UIBackgroundAdjustor : MonoBehaviour
12 {
13     float standard_width = 1024f;
14     float standard_height = 600f;
15     float device_width = 0f;
16     float device_height = 0f;
17 
18     void Awake()
19     {
20         device_width = Screen.width;
21         device_height = Screen.height;
22 
23         SetBackgroundSize();
24     }
25 
26     private void SetBackgroundSize()
27     {
28         UISprite m_back_sprite =   GetComponent<UISprite>();
29 
30         if (m_back_sprite != null &&   UISprite.Type.Simple == m_back_sprite.type)
31         {
32               m_back_sprite.MakePixelPerfect();
33             float back_width =   m_back_sprite.transform.localScale.x;
34             float back_height =   m_back_sprite.transform.localScale.y;
35 
36             float standard_aspect =   standard_width / standard_height;
37             float device_aspect =   device_width / device_height;
38             float extend_aspect =   0f;
39             float scale = 0f;
40 
41             if (device_aspect >   standard_aspect) //按宽度适配
42             {
43                 scale =   device_aspect / standard_aspect;
44 
45                 extend_aspect   = back_width / standard_width;
46             }
47             else //按高度适配
48             {
49                 scale =   standard_aspect / device_aspect;
50 
51                 extend_aspect   = back_height / standard_height;
52             }
53 
54             if (extend_aspect >=   scale) //冗余尺寸足以适配,无须放大
55             {
56             }
57             else   //冗余尺寸不足以适配,在此基础上放大
58             {
59                 scale /=   extend_aspect;
60                   m_back_sprite.transform.localScale *= scale;
61             }
62         }
63     }
64 }




0 0
原创粉丝点击