一、当下移动设备的主流分辨率(数据来自“腾讯分析移动设备屏幕分辨率分析报告”)
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;
3
4 /// <summary>
5 /// 根据设备的宽高比,调整camera.orthographicSize. 以保证UI在不同分辨率(宽高比)下的自适应
6 /// 须与UIAnchor配合使用
7 /// 将该脚本添加到UICamera同一节点上
8 /// </summary>
9
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;
3
4 /// <summary>
5 /// 根据设备的宽高比,调整UISprite scale, 以保证全屏的背景图在不同分辨率(宽高比)下的自适应
6 /// 将该脚本添加到UISprite同一节点上
7 /// 须与UICameraAdjustor脚本配合使用
8 /// </summary>
9
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 }

Unity3d + NGUI 的多分辨率适配的更多相关文章

  1. 【转】Unity3d + NGUI 的多分辨率适配

    原文地址:http://www.cnblogs.com/cqgreen/p/3348154.html   一.当下移动设备的主流分辨率(数据来自“腾讯分析移动设备屏幕分辨率分析报告”) 1.1 iOS ...

  2. Unity3d + NGUI 的多分辨率适配(黑边)

    原地址:http://www.2cto.com/kf/201310/250921.html 一.当下移动设备的主流分辨率(数据来自“腾讯分析移动设备屏幕分辨率分析报告”) 1.1 iOS设备的分辨率主 ...

  3. Unity NGUI的多分辨率适配

    参考链接:http://blog.csdn.net/mfc11/article/details/17681429,作者:CSDN mfc11 1.NGUI默认的适配方式: NGUI默认是适配方式是根据 ...

  4. Unity3d + UGUI 的多分辨率适配

    原文地址:http://blog.csdn.net/dingkun520wy/article/details/49471789 1.Canvas的属性配置 2.Canvas Scaler的属性配置 3 ...

  5. Unity3D NGUI自适应屏幕分辨率(2014/4/17更新)

    原地址:http://blog.csdn.net/asd237241291/article/details/8126619 原创文章如需转载请注明:转载自 脱莫柔Unity3D学习之旅 本文链接地址: ...

  6. Cocos与Cocos2d-x协作教程——多分辨率适配

    http://www.cocoachina.com/bbs/read.php?tid-288123.html Cocos v2.1开始新增了一种新的多分辨率适配方案:流式布局. 这种布局相比Cocos ...

  7. Android多分辨率适配

    前一阶段开发android项目,由于客户要求进行多分辨率适配,能够支持国内主流的分辨率手机.因此经过了几次开发走了很多弯路,目前刚刚领略了android多分辨率适配的一些方法. 先介绍一下所走的弯路, ...

  8. Android多分辨率适配经验总结

      Android多分辨率适配是一件很有意义但是比较麻烦的事情,网上有很多关于多分辨率适配的文章,多数文章讲解的都是整个APP的图片比较规则,可以将图片做成9图来完成多分辨率适配,但是对于一些游戏类应 ...

  9. Unity3D NGUI学习(一)血条

    这次来讲讲Unity3D NGUI这个插件的学习,这个插件是收费的,不过去网上可以下载得很多可用版本.用来做用户的交互UI,学习起来比较简单 第一步,导入NGUI包 http://pan.baidu. ...

随机推荐

  1. 菜单的隐藏&显示

    //还是先上万一老师的原代码 //隐藏与显示菜单Self.Menu := nil; {隐藏菜单} Self.Menu := MainMenu1; {显示菜单} //初一看到代码,我有点抓不到感觉的意思 ...

  2. oracle 11gr2 官方文档下载

    http://www.oracle.com/technetwork/database/enterprise-edition/documentation/index.html

  3. 判断Window在哪个屏幕

    最近在做窗口最大化时需要一个功能,如果是多个显示器的话,需要在当前显示器最大化,由于是根据屏幕长宽进行设置Window大小,没有使用WindowState.Maximized,window.Left不 ...

  4. netload 加载程序集抛异常----无法加载程序集解决办法

    netload 加载程序集抛异常----无法加载程序集 错误信息如下: 无法加载程序集.错误详细信息: System.BadImageFormatException: 未能加载文件或程序集“file: ...

  5. Lessons Learned 1(敏捷项目中的变更影响分析)

    问题/现象: 业务信息流转的某些环节,会向相关人员发送通知邮件,邮件中附带有链接,供相关人员进入察看或处理业务.客户要求邮件中的链接,需要进行限制,只有特定人员才能进入处理或察看.总管想了想,应道没问 ...

  6. Tomcat如何配置环境变量

    1, JDK:版本为jdk-7-windows-i586.exe 下载地址: http://www.oracle.com/technetwork/java/javase/downloads/index ...

  7. 为什么LTE系统的最小时间单位是Ts?

    之前一直在做LTE物理层相关的工作,一直有个疑惑, 在36.211开头的一章定义Ts的大小是1/(15000*2048)s,为什么定义这么一个奇怪的unit time. 最近才反应过来,这跟FFT/I ...

  8. Height Half Values

    public class HeightDemo { /** * 题目:一球从100米高度自由落下,每次落地后反跳回原高度的一半: * 再落下,求它在第10次落地时,共经过多少米?第10次反弹多高? * ...

  9. 设计模式可复用面向对象软件设计基础之对象创建型模式—ABSTRACT FACTORY( 抽象工厂)

    意图 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 适用性 在以下情况可以使用 Abstract Factory模式 • 一个系统要独立于它的产品的创建.组合和表示时. • 一 ...

  10. 【CronExpression表达式详解和案例】

    1. cron表达式格式: {秒数} {分钟} {小时} {日期} {月份} {星期} {年份(可为空)} 2. cron表达式各占位符解释: {秒数} ==> 允许值范围: 0~59 ,不允许 ...