Unity+NGUI多分辨率适配方案

  说起unity的适配方案,网上可谓是一查一大堆,但是真正要应用到项目中的时候,总会出现各式各样的问题。由于最近自己要做一个小游戏,在开始做游戏之前,就想着先好好搞一搞适配这块,以后新起项目的时候也会用得着。

NGUI应该是现在大部分开发者都会去选择的UI插件,虽然NGUI还存在着不少问题,像是相对来说,NGUI还是比较靠谱的,所以这里只是针对NGUI做适配方案。

  NGUI中对于每一个场景,都是以UIRoot为GameObject树的根的,UIRoot下面主要有这几种属性

  

1) Scaling Style

UIRoot有几种缩放方式

  方式1:    PixelPerfect 这种方式下,你的UI一直都是以像素为基础,一个300*200的widget在屏幕上永远占用300*200像素。这就意味着,你的UI在低分辨率的机器上会显得非常大,在高分辨率的机器上就会显得很小。这个设置就是一直保持你的UI清晰。

  方式2:  FixedSize是一个和它功能正好相反的设置。当UIRoot用了这个选项,你的屏幕永远都会保持NGUI所关心的尺寸,不管你的实际屏幕是多大。就是说一个300*200的widget占用了你1920*1080的25%的屏幕,那么当分辨率降低到1280*720的时候,它同样占用25%的屏幕。如果你不介意你的UI看起来像是不同的尺寸,也不关心是否清晰(就是可能一个小的UI被拉伸很大),那么选择这个选项。选择它的时候,不要忘记设置Manual Height。

这个占的百分比就是通过widget的尺寸和当前你设置的Manual的尺寸而算出来,所以当你移植到不同的移动设备时,它会根据这个占比和移动设备的实际分辨率进行运算,然后算出显示的实际像素大小。即Scaling Style指定为FixedSize或FixedSizeOnMobiles,则缩放只以Manual Height为参考,屏幕分辨率的高度值不同于此设置值时,则根据其比例(即Screen Height / Manual Height)对整棵UI树的进行“等比”缩放(宽度的缩放比也是此比例值)。

  方式3: FixedSizeOnMobile是前两种的组合。选择这个选项后,会在pc或者mac等桌面设备上用“PixelPerfect”,在移动设备上用“FixedSize”。

如果你没有选择Fixed Size选项,那就要设置Minimum和Maximum Height的值。这些值让你的虚拟屏幕看起来在合理范围。比如选择了Pixel Perfect方式,Minimum Height设置为720,那么当有玩家把你的程序运行在800*600(高度是600,小于Minimun Height)的设备上时,你UI的行为就和设置了“Fixed Size”模式、Manual Height值设为720的时候一样。

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

下面用实际例子来验证各个方式的实际效果

Pixel Perfect下,先将Minimum和Maximum Height 分别设置为500,1500,然后用NGUI做出期望UI,如下

下面是在各个分辨率下的实际显示情况

1024*768

1920 * 1080

其他的就不一一罗列了,我们发现中间的图片一直保持着原大小没有变化,至于背景图会超出屏幕外的问题,我们可以通过设置Anchor的方法来解决,将背景图的四边对齐UIRoot的四边,四个角的方块按钮的Anchor以背景图为目标,效果如下:

很明显这样的效果和期望设计UI的对比是让人难以接受的,所以现在市面的手机游戏几乎没有使用Pixel Perfect做适配方案的.....

下面把Pixel Perfect改成Fix Size,UI背景图和四个角的anchor保持不变,

这样的效果是可以接受的,这里面还有一个问题,那就是因为设置了anchor,导致背景图会有拉伸的情况,而且如果使用anchor来做适配的话,前端程序员的工作量太大了。所以我们还是去掉anchor,想想其他办法。

这里面我们先将UIRoot设置为

然后1280 * 720 作为默认分辨率,然后背景图大小也统一设置为1280 * 720,做好一个简单的界面

然后将UI放到960 * 640的分辨率上显示 ,因为1280 * 720 是16:9的屏幕,而960 * 640 是3:2的屏幕,所以会导致宽度上无法全部显示出来

这时候有以下几种解决方法

方法1:动态更改UIRoot的Manual Height

     在960 * 640的屏幕下,由于Manual Height = 720,所以720放到640的高度下需要缩放640/720 = 8/9, 由于UI是按照1280*720的尺寸设计的,所以UI的宽度缩为1280 * 8/9 = 1137.7,明显960的宽度根本放不下,所以我们要继续更改缩放系数,使其

能够在960的宽度下完全显示,而这个缩放系数是根据屏幕尺寸和Manual Height算出来的,所以我们只需要动态的去计算Manual Height,就可以很好的将UI整体放进屏幕中了。

 以前看过的代码,挂到UIRoot下面

 1 using UnityEngine;
 2 using System.Collections;
 3
 4 public class UIAdapter : MonoBehaviour {
 5
 6     public int ManualWidth = 1280;
 7     public int ManualHeight = 720;
 8
 9     void Awake ()
10     {
11         AdaptiveUI();
12     }
13
14     private void AdaptiveUI()
15     {
16
17         UIRoot uiRoot = GetComponent<UIRoot>();
18         if (uiRoot != null)
19         {
20             if (System.Convert.ToSingle(Screen.height) / Screen.width > System.Convert.ToSingle(ManualHeight) / ManualWidth)
21                 uiRoot.manualHeight = Mathf.RoundToInt(System.Convert.ToSingle(ManualWidth) / Screen.width * Screen.height);
22             else
23                 uiRoot.manualHeight = ManualHeight;
24         }
25     }
26 }

此时运行

这种方法上下会留有黑边,黑边如果感觉不能忍受,也可以做一些处理,后面的方法也都是带黑边的,至于怎么优化这些黑边,后面再研究。

但是如果NGUI版本过低的话,这种方案可能会导致UIPanel的裁剪功能失效。所以再看看下面的方法。

方法2:调整UICamera的orthographicSize

这种方法即通过更改相机的正交尺寸来做UI自适应, 当相机为正交时,即像这样:

看起来像是一个立方体的框框,这个框框就是相机所能显示的范围,orthographicSize变化时,框框的宽高会相应变化,比如我们将orthographicSize缩小为0.5

看到相机的正交面也缩小了0.5,所以屏幕上显示的UI也为原来的一半,那么上面提到的如果1280*720的图片放到960*640的屏幕下,宽度不够的问题,我们可以适当放大一下orthographicSize,这样就可以将UI完全显示到屏幕中。

直接上代码,http://blog.csdn.net/dingkun520wy/article/details/26084045,感谢这位同学,只是代码有点小错误,改过以后,挂到UIRoot的相机上

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(UICamera))]
public class UIAdapterCamera : MonoBehaviour
{
    float standard_width = 1280f;        //初始宽度
    float standard_height = 720f;       //初始高度
    float device_width = 0f;                //当前设备宽度
    float device_height = 0f;               //当前设备高度
    public float adjustor = 0f;         //屏幕矫正比例
    void Awake()
    {

        //获取设备宽高
        device_width = Screen.width;
        device_height = Screen.height;
        //计算宽高比例
        float standard_aspect = standard_width / standard_height;
        float device_aspect = device_width / device_height;
        //计算矫正比例
        if (device_aspect < standard_aspect)
        {
            adjustor = standard_aspect / device_aspect;
            //Debug.Log(standard_aspect);
        }
        Debug.Log("屏幕的比例" + adjustor);
        if (adjustor < 2 && adjustor > 0)
        {
            camera.orthographicSize = adjustor;
        }

    }
    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }
}

然后960 * 640显示是这样子的

看到红框处的数值由1变为1.18...了。OK。

到这里看起来这个方案应该可以了吧,其实这里面还有一个问题,那就是相机不是正交时,Orthographic size被忽略,就是说这个脚本只能用来解决2d相机的适配问题,某些非正交相机的适配还是无法实现,所以该方案也pass掉。

方法3: 更改相机的rect值,就是编辑器里面对应的ViewPort Rect

camera的rect默认为(0,0,1,1) ,(0,0)对应屏幕的左下角位置,(1,1)分别对应屏幕宽的百分比和高的百分比,所以默认相机的rect范围是从左下角到屏幕右上角,即为全屏。

这样的话,我们可以通过实际屏幕的分辨率和设计分辨率,来实际计算出相机视角的范围

上代码,挂到camera下

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(Camera))]
public class MyCameraAdapter : MonoBehaviour
{

    public Camera camera;

    void Start()
    {
        AdaptCamera();
    }

    public void AdaptCamera()
    {
        if (camera == null)
        {
            camera = GetComponent<Camera>();
        }

        float screenAspect = Screen.width / Screen.height;
        float designAspect = 1280 / (float)720;

        if (designAspect < screenAspect) //屏幕分辨率过大,宽度过长,则屏幕横向留出黑边,高度不变
        {
            float tarWidth = Screen.height * designAspect;//求出实际要显示的宽度
            float tarWidthRadio = tarWidth / Screen.width;//求出宽度百分比
            float posW = (1 - tarWidthRadio) / 2;//宽的起点
            camera.rect = new Rect(posW, 0, tarWidthRadio, 1);
        }
        else if (designAspect > screenAspect)//屏幕分辨率过小,高度过高,纵向留黑边,宽度不变
        {
            float tarHeight = Screen.width  / designAspect;
            float tarHeightRadio = tarHeight / Screen.height;
            float posH = (1 - tarHeightRadio) / 2;
            camera.rect = new Rect(0, posH, 1, tarHeightRadio);
        }
        else
        {
            camera.rect = new Rect(0, 0, 1, 1);
        }
    }
}

 这样的话无论是2d相机还是3d相机,都可以挂载这个脚本做适配。这样算是一个完美的解决方案了吧,至于黑边,有时间再优化。

时间: 2024-10-13 11:44:36

Unity+NGUI多分辨率适配方案的相关文章

cocos2d-x多分辨率适配方案:setDesignResolutionSize使用

1. setDesignResolutionSize使用方法及主要的三种适配模式 在cocos2d-x 2.0里,提供了一个叫做setDesignResolutionSize的方法,直接一次设置就可以自动适配各种分辨率.这个方法的注释如下: enum ResolutionPolicy { kResolutionExactFit, kResolutionNoBorder, kResolutionShowAll, kResolutionFixedHeight, kResolutionFixedWid

cocos2dx-安卓多分辨率适配方案

#include "AppDelegate.h" #include "HelloWorldScene.h" #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) // Layer #include "OperateLayer.h" #include "LoginMainLayer.h" #include "OperateUILayer.h" #include "G

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

http://www.cocoachina.com/bbs/read.php?tid-288123.html Cocos v2.1开始新增了一种新的多分辨率适配方案:流式布局. 这种布局相比CocosStudio v1.x时代简单纯粹得多,没那么多复杂的概念也没那么难理解,上手更简单,这篇教程就是来教大家怎么使用这个功能的. 实际上之前也写过一篇布局教程,不过反响感觉不太好,不少人看完之后还有不少疑问,尤其是跟2d-x协作相关的疑问.因此,这次提供一个更给力的版本,从Cocos编辑配置到与Coc

Unity2D多分辨率屏幕适配方案(转载)

一下内容转自:http://imgtec.eetrend.com/forum/3992 此文将阐述一种简单有效的Unity2D多分辨率屏幕适配方案,该方案适用于基于原生开发的Unity2D游戏,即没有使用第三方2D插件,如Uni2D,2D toolkit等开发的游戏,NGUI插件不受这个方案影响,可以完美和此方案配合使用. 先说明一些基本的概念: 1.屏幕的宽高比Aspect Ratio = 屏幕宽度/屏幕高度 2.Unity2D中摄像机镜头的尺寸决定了我们实际看到游戏内容的多少,在编辑器中我们

[原创]一种Unity2D多分辨率屏幕适配方案

此文将阐述一种简单有效的Unity2D多分辨率屏幕适配方案,该方案适用于基于原生开发的Unity2D游戏,即没有使用第三方2D插件,如Uni2D,2D toolkit等开发的游戏,NGUI插件不受这个方案影响,可以完美和此方案配合使用. ---------------------------------------正式开始的分割线----------------------------------------- 先说明一些基本的概念: 1.屏幕的宽高比Aspect Ratio = 屏幕宽度/屏幕

一种Unity2D多分辨率屏幕适配方案

此文将阐述一种简单有效的Unity2D多分辨率屏幕适配方案,该方案适用于基于原生开发的Unity2D游戏,即没有使用第三方2D插件,如Uni2D,2D toolkit等开发的游戏,NGUI插件不受这个方案影响,可以完美和此方案配合使用. ---------------------------------------正式开始的分割线----------------------------------------- 先说明一些基本的概念: 1.屏幕的宽高比Aspect Ratio = 屏幕宽度/屏幕

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

原文地址:http://www.cnblogs.com/cqgreen/p/3348154.html 一.当下移动设备的主流分辨率(数据来自“腾讯分析移动设备屏幕分辨率分析报告”) 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 72

【Unity NGUI游戏开发之五】多分辨率下完美分布式协同开发

NGUI多分辨率下完美分布式协同开发:不同分辨率下相对于屏幕坐标的Perfab数据不再丢失 NGUI多分辨率下完美分布式协同开发不同分辨率下相对于屏幕坐标的Perfab数据不再丢失 开发问题 原因分析 案例 完美过程 案例分析 实现过程 开发问题: NGUI分布式开发中,用git管理资源,团队成员每人负责一个perfab,所有现对于屏幕大小的相对位置的perfab因为引用了perfab外的数据,导致perfab的Anchor锚点数据丢失,最后的perfab集成后,必须重新设置,导致开发成本大幅度

【Unity NGUI游戏开发之三】TweenPosition位移动画(二):相对于UIAnchor不同分辨率下的完美适配位移动画

Unity中的UI我们采用的是NGUI,NGUI的界面位移动画,我们一般使用的是TweenPosition. 一种是简单的相对位移,不考虑分辨率适配问题,只需要简单的从位置A到位置B,已经在文中介绍了: [Unity NGUI游戏开发之二]TweenPosition位移动画(一):不相对于Anchor的位移动画 另外一种是考虑到屏幕分辨率适配的位移动画,我们游戏中大多遇到的是这种情况. eg.我们想让一个UI从屏幕外沿着屏幕的左边移动到屏幕的中央,TweenPositon播放动画,在960*64