Unity GUI自适应屏幕分辨率(一)布局自适应

这里我们先谈第一个问题坐标矩阵变化实现布局自适应。

选取基准尺寸

通常你需要选择一个基准的屏幕尺寸,象现在开发的应用也需要跨平台在iOS(iPhone/iPad)/Android都可以运行,我这边选取的是iphone4的屏幕尺寸:
480 * 320.
设计师设计的GUI的素材时就是按照这个尺寸来设计。但是紧接着的问题是如何保证它在其他不同尺寸/分辨率的平台上运行时不会出现各种诡异的位置大小错乱了。

举一个实际的例子来更好描述这个问题,比如我们的游戏是水平方向的,
然后游戏进行中间的暂停界面中,有三个角落有按钮或着标签,屏幕中间有一个按钮,如下图所示:

很简单的代码:


void OnGUI()
{

GUI.Box(new Rect(15 , 10, 83, 49), bg_score);
GUI.Box(new Rect(372, 10, 98, 44), bg_time);

if (GUI.Button(new Rect(5, 280, 67, 41), bt_pause))
{
//pause the scene
}

}

伸缩居中


在Unity中我们将Game窗口的模式选择为iPhone Wide(480x320), 然后运行游戏,
木有什么问题。 紧接着尝试运行在iPhone 4G Wide(960x640),
你就会发现问题了,整个格局错乱了,并没有有比例的伸缩,然后全部堆到了左边.

所以可以想到既然有了基准的屏幕尺寸,其他尺寸的处理必然需要针对这个基准来变化,
我们需要的是在基准屏幕上各个元素都按照一定的比例放大或者缩小,水平和竖直方向的伸缩比列一定得是同步的,这样一来保证它们之间的相对位置保持不变。在Unity中GUI系统中我们就需要运用到GUI.Matrix矩阵变化。

要解决这个问题,我们可以定义一个基准尺寸,我们这里是480*320.


public static Vector2 NativeResolution = new Vector2(480, 320);

然后了,我们要让长宽按照这个基准来变化,包括首先是伸缩放大或缩小,其次是在变化之后使其保持居中。


private static float _guiScaleFactor = -1.0f;
private static Vector3 _offset = Vector3.zero;

static List<Matrix4x4> stack = new List<Matrix4x4> ();
public void BeginUIResizing()
{
Vector2 nativeSize = NativeResolution;

_didResizeUI = true;

stack.Add (GUI.matrix);
Matrix4x4 m = new Matrix4x4();
var w = (float)Screen.width;
var h = (float)Screen.height;
var aspect = w / h;
var offset = Vector3.zero;
if(aspect < (nativeSize.x/nativeSize.y))
{
//screen is taller
_guiScaleFactor = (Screen.width/nativeSize.x);
offset.y += (Screen.height-(nativeSize.y*guiScaleFactor))*0.5f;
}
else
{
// screen is wider
_guiScaleFactor = (Screen.height/nativeSize.y);
offset.x += (Screen.width-(nativeSize.x*guiScaleFactor))*0.5f;
}

m.SetTRS(offset,Quaternion.identity,Vector3.one*guiScaleFactor);
GUI.matrix *= m;
}

public void EndUIResizing()
{
GUI.matrix = stack[stack.Count - 1];
stack.RemoveAt (stack.Count - 1);
_didResizeUI = false;
}

紧着这我们在OnGUI方法中的开头和结尾分别调用BeginUIResizing和EndUIResizing来变化矩阵。


void OnGUI()
{
BeginUIResizing(); //call this in the beginning of method

GUI.Box(new Rect(15 , 10, 83, 49), bg_score);
GUI.Box(new Rect(372, 10, 98, 44), bg_time);

if (GUI.Button(new Rect(5, 280, 67, 41), bt_pause))
{
//pause the scene
}

EndUIResizing(); //call this in the end of method
}

这里我们根据长宽比,算出伸缩比例,然后为了保证伸缩之后的画面能始终在屏幕中间,我们要算出多出来偏移量,最后我们根据这个偏移量和缩放比例对矩阵进行变化。

然后我们再在分辨率为960*640的情况下运行。

  • iPhone4 960 * 640:

  • iPhone5 1136 * 640:

  • iPad 1024 * 768:

你可以看到在其他尺寸的屏幕上伸缩都没有问题,而且元素都居中。但是有一个问题,你发现在iPhone5和iPad上几个标签按钮的位置有点不太对,他们需要像iPhone4一样紧贴两边,而在iPhone5和iPad上却不是这样。

偏移量

要想解决这个问题的理解这个矩阵变化是如何工作的。这个偏移量是变换之后算出来的偏移量。所以要想让GUI元素在变换之后依然在保持屏幕的边缘,我们需要将x,y减去这偏移量,于是有了下面的代码:


void OnGUI()
{
BeginUIResizing(); //call this in the beginning of method

GUI.Box(new Rect(15 - offset.x/guiScaleFactor , 10 - offset.y/guiScaleFactor,
83, 49), bg_score);
GUI.Box(new Rect(372 + offset.x/guiScaleFactor, 10 - offset.y/guiScaleFactor,
98, 44), bg_time);

if (GUI.Button(new Rect(5 - offset.x/guiScaleFactor, 280 + offset.y/guiScaleFactor,
67, 41), bt_pause))
{
//pause the scene
}

EndUIResizing(); //call this in the end of method
}

这里要记住这个偏移量是offset.x/guiScaleFactor, 而不是offset.x, 因为这个坐标是基于基准矩阵来的。

将代码重新跑一遍:

  • iPhone5 1136*640

  • iPad 1024 * 768:

这个木有问题了。

时间: 2024-10-12 22:05:16

Unity GUI自适应屏幕分辨率(一)布局自适应的相关文章

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

原地址:http://blog.csdn.net/asd237241291/article/details/8126619 原创文章如需转载请注明:转载自 脱莫柔Unity3D学习之旅 本文链接地址:Unity3D NGUI自适应屏幕分辨率 1.UIRoot:根据高度自适应屏幕分辨率. NGUI根目录的UIRoot组件自带了根据高度自适应分辨率的功能. Scaling Style属性可选择三种不同的缩放策略. PixelPerfect 完美像素:直接显示设定好的像素.当屏幕高度低于minimum

Delphi 窗体自适应屏幕分辨率的改进

Delphi:窗体自适应屏幕分辨率的改进 http://blog.sciencenet.cn/blog-39148-544498.html 在窗体依据屏幕分辨率自适应调整尺度方面,昨天的工作可以说是一个突破点.昨天的工作找到了长期以来我的原有方案的问题所在,这是非常关键的.但是昨天晚上的解决方案并不完美,今天的这个才是比较完美的解决版. 先补充说明一下这个问题的重要性.这本来只是一个很小的技术问题,但在现有的Windows软件开发过程中,这个问题非常常见.一些非常著名的商业化软件,也会发现这方面

jQuery Easy UI (适应屏幕分辨率大小)布局(Layout)

一.jQuery Easy UI (适应屏幕分辨率大小)布局(Layout) 1.首先应用的是jquery-easyui-1.4 版本(版本不同,兼容性不同) 2.实现整个页面的布局( layout: north,south,west,east, center) 3.首先整个页面布局适应屏幕的分辨率大小 4.然后内容区域进行布局,也要适应屏幕分辨率大小 5.部分代码: 1 <body> 2 <div class="easyui-layout" fit="tr

Unity NGUI根据高度自适应屏幕分辨率

Unity版本:4.5.1 NGUI版本:3.6.5 本文内容纯粹转载,转载保留参考链接和作者 参考链接:http://blog.csdn.net/asd237241291/article/details/8126619,作者:CSDN 脱莫柔 NGUI根目录的UIRoot组件自带了根据高度自适应分辨率的功能. Scaling Style属性可选择三种不同的缩放策略: PixelPerfect 完美像素:直接显示设定好的像素.当屏幕高度低于minimum Height时按比例缩小,当屏幕高度大于

窗体自适应屏幕分辨率

话说Delphi有个很强的窗体设计器,这一点让VC粉丝垂涎三尺而不可得.但是,Delphi里设计的窗体并没有自动适应屏幕分辨率的属性,也就是说,软件设计时调整完美的窗体控件布局,在不同屏幕分辨率的机器上运行时可能会变得面目全非.控件之间会相互移位,有的甚至移出窗体再也找不到了. 这个问题在网上搜索过多次,但大都依据控件方法ScaleBy或者ChangeScale.采用这两个方法进行自适应调整,我自己都试过,但效果并不理想.后来我自己也写了一个继承自窗体的基类,覆盖构造函数,调用自己的一个设备分辨

2015.3.10(自适应屏幕和弹性布局)

今天做的练习是自适应屏幕大小,遇到了一些困难,困难在于我以前用CSS布局的时候都是使用PX作为单位来进行定位布局. 但今天把网页拓展实验到了我家的电视(42寸)上,此时就出现了问题,问题之一就是:没有办法填充满屏幕,只能出现一个屏中屏,看起来非常的别扭. 试验了纯CSS来做到自适应屏幕和用JS获取屏幕大小然后计算比例填写在CSS中两种方法均不是很满意,问题直到现在也没有解决,在问题解决之前先把这个问题解决过程记录下来. html部分的代码是这样的 CSS部分的代码是这样的: body{ font

rem实现页面自适应屏幕分辨率

<html> <body> <div class="test"></div> </body> </html> 默认情况下1rem=16px;   font-size: 62.5%, 1rem=10px;   以下按照屏幕分辨率设置font-size的百分率, 可以保证div的宽高比在不同分辨率下保持一致,    页面字体大小使用rem同理 /*根据屏幕分辨率自适应大小*/ @media (max-width:192

Delphi:窗体自适应屏幕分辨率(根据预设值的比例改变)

delphi 程序适应屏幕分辨率,先在表单单元的Interface部分定义两个常量, 表示设计时的屏幕的宽度和高度(以像素为单位). 在表单的Create事件中先判断 当前分辨率是否与设计分辨率相同, 如果不同,调用表单的SCALE过程重新能调整表单中控件的宽度和高度. Const   Orignwidth=800;   Orignheight=600; procedure TForm1.FormCreate(Sender:TObject); begin scaled:=true; if (sc

如何让Android字体自适应屏幕分辨率

在不同的分辨率下,Android字体大小怎么自适应分辨率的变化? 假设需要适应320x240,480x320分辨率.在res目录下新建文件夹values-320x240, values-480x320.然后在文件夹 values ,values-320x240 和 values-480x320 下新建xml文件dimens.xml,该xml文件内容如下: <?xml version="1.0" encoding="utf-8"?> <resourc