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:

这个木有问题了。
Unity GUI自适应屏幕分辨率(一)布局自适应的更多相关文章
- delphi 窗体自适应屏幕分辨率
		delphi 窗体自适应屏幕分辨率 这是个困惑我很长时间的问题,到今天终于得到解决了. 话说Delphi有个很强的窗体设计器,这一点让VC粉丝垂涎三尺而不可得.但是,Delphi里设计的窗体并没有自动 ... 
- #region 自适应屏幕分辨率
		#region 自适应屏幕分辨率 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public ... 
- Unity3D NGUI自适应屏幕分辨率(2014/4/17更新)
		原地址:http://blog.csdn.net/asd237241291/article/details/8126619 原创文章如需转载请注明:转载自 脱莫柔Unity3D学习之旅 本文链接地址: ... 
- jQuery Easy UI (适应屏幕分辨率大小)布局(Layout)
		一.jQuery Easy UI (适应屏幕分辨率大小)布局(Layout) 1.首先应用的是jquery-easyui-1.4 版本(版本不同,兼容性不同) 2.实现整个页面的布局( layout: ... 
- Unity NGUI根据高度自适应屏幕分辨率
		Unity版本:4.5.1 NGUI版本:3.6.5 本文内容纯粹转载,转载保留参考链接和作者 参考链接:http://blog.csdn.net/asd237241291/article/detai ... 
- H5自适应屏幕分辨率大小
		说明: ①:H5自适应不同分辨率的设备,其实主要就一句 <meta name="viewport" content="width=device-width,init ... 
- NGUI自适应屏幕分辨率
		unity官方承诺的新ui系统一直没有推出来,我们的UI使用的是原生的OnGUI系统,刚好UI需要改版,索性就想迁到NGUI上面来,于是看了一下NGUI源码,发现NGUI可以大大的降低DrawCall ... 
- Delphi:窗体自适应屏幕分辨率的改进
		在窗体依据屏幕分辨率自适应调整尺度方面,昨天的工作可以说是一个突破点.昨天的工作找到了长期以来我的原有方案的问题所在,这是非常关键的.但是昨天晚上的解决方案并不完美,今天的这个才是比较完美的解决版. ... 
- Delphi:窗体自适应屏幕分辨率(根据预设值的比例改变)
		delphi 程序适应屏幕分辨率,先在表单单元的Interface部分定义两个常量, 表示设计时的屏幕的宽度和高度(以像素为单位). 在表单的Create事件中先判断 当前分辨率是否与设计分辨率相同, ... 
随机推荐
- Win10易升是什么?如何彻底关闭Windows10易升?
			很多朋友反馈在使用电脑的时候,突然弹出一个微软Windows10易升的界面,那么Win10易升是什么,怎么样才可以彻底关闭Win10易升呢? win10易升是什么 1.易升是微软官方发布的升级助理或者 ... 
- angularjs Dom方式访问疑似可以访问ifame结构项目
			一.定位需要访问控制器元素 var currObj = document.querySelector('[ng-controller="munuListCtrl"]'); 或者 v ... 
- C语言,C#,Java,JavaScript之强类型与弱类型
			奇葩的我今天想到一个坑爹的问题,都说Java是强类型的语言,JavaScript是弱类型的语言. 嗯嗯,那初学时候的C语言呢? 呵呵哒,突然觉得短路了.说Java是强类型的语言是因为遇到这样的情况: ... 
- skynet 创建存储过程脚本
			最近主程更改了数据库的操作方案,由之前的拼写sql脚本转为在mysql端创建好存储过程后,直接调用存储过程. 首先对一个表测试上述过程: 数据库端存储过程:(测试表) CREATE TABLE `ra ... 
- javascript打开新页面的方法
			方案一: A标签: 这里要注意target的设置,_Blank是指新窗口,也可以用js来模拟创建. <a href="http://www.cnblogs.com" targ ... 
- Android -- SQLite 数据库创建,增删改查,事务处理
			1. 概述 在Android平台上,集成了一个嵌入式关系型数据库-SQLite,SQLite3支持 NULL.INTEGER.REAL(浮点数字).TEXT(字符串文本)和BLOB(二进制对象)数据类 ... 
- RxJava+RxAndroid+MVP入坑实践(基础篇)
			转载请注明出处:http://www.blog.csdn.net/zhyxuexijava/article/details/51597230.com 前段时间看了MVP架构和RxJava,最近也在重构 ... 
- LeetCode第[26]题(Java):Remove Duplicates from Sorted Array  标签:Array
			题目难度:Easy 题目: Given a sorted array, remove the duplicates in-place such that each element appear onl ... 
- 编写程序时候莫名出现<property name="dialect">org.hibernate.dialect.FirebirdDialect</property>
			把<propertyname="dialect">org.hibernate.dialect.FirebirdDialect</property> 语句去掉 ... 
- linux安装----gcc
			Linux中gcc是个编译工具,可以将源码文件(c c++ java文件) 编译成 二进制文件. 
