一、当下移动设备的主流分辨率(数据来自“腾讯分析移动设备屏幕分辨率分析报告”)
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. LogNet4日志框架使用

    .百度一下log4dll下载 .webconfig 里的<configSetions>节点中添加 <section name="log4net" type=&qu ...

  2. Android Service完全解析,关于服务你所需知道的一切(下)

    转载请注册出处:http://blog.csdn.net/guolin_blog/article/details/9797169 在上一篇文章中,我们学习了Android Service相关的许多重要 ...

  3. java TreeMap用法

    转自:http://huchenqiang90.blog.163.com/blog/static/11250080020101025956498/ 最近工作遇到需要按一个model中不同的列进行排序的 ...

  4. IIS出现问题时修改配置文件的几项说明

    近期系统在线运行经常出现object moved错误 通过查询资料,做了几项web.config文件的调整 1,调整应用程序池使用集成模式      <system.webServer>  ...

  5. 我与solr(二)--导入mysql数据库

    关于solr的搭建详见上一篇的随笔. 步骤1: 在webapps中solrhome下新建一个文件夹名字叫做mynode(名字不固定,可以随便取,但是这个名字在后面的配置中会有所关联.)然后在mynod ...

  6. IE8控件安装方法

    打开上传页面,IE提示安装控件,点击安装     刷新网页,点击允许运行加载项,需要允许两次  

  7. 黑马程序员-autorelease pool

    Autorelease:可以延迟给对象发送release消息.发送一个autorelease消息给对象,证明该对象在一定时间内有效,一定时间后会对该对象进行释放,进行一次release. 一个auto ...

  8. hdu 3397 Sequence operation(线段树:区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意:给你一个长度为n的0,1序列,支持下列五种操作, 操作0(0 a b):将a到b这个区间的 ...

  9. 『TCP/IP详解——卷一:协议』读书笔记——18

    2013-08-27 15:44:52 第7章 Ping程序 7.1 引言 “ping”这个名字来源于声纳定为操作.Ping程序由Mike Muuss编写,目的是为了测试另一台主机是否可达.该程序发送 ...

  10. Linux Ubuntu12.04下安装OpenCv2.4.10

    参考 http://blog.sina.com.cn/s/blog_53b0956801010lfu.html 捣鼓了一个晚上了,OpenCv还没装好,本来以为看个类似的比如Ubuntu安装OpenC ...