为什么新建的uiroot会很小 unity3d uiroot

转自:http://blog.csdn.net/yaokang522/article/details/
UIRoot是NGUI最根本和最重要的脚本,在实际UI开发过程中都是以UIRoot为根的GameObject树,那他的作用到底是什么,先看下UIRoot的Inspection选项:
看到这个,大致可以猜到是跟UI界面缩放有关的,而且是基于高度放缩的。
Scaling Style参数
& & & &到底每个参数(Scaling Style, Manual Height ,Minimum Height 和MaximumHight)的作用和区别是什么,在没有其他先验知识的情况下,只有去看代码了。
public&enum&Scaling&&&&&&{&&&&&&&&&&PixelPerfect,&&&&&&&&&&FixedSize,&&&&&&&&&&FixedSizeOnMobiles,&&&&&&}&&
& & & &Scaling Style参数的作用是制定UIRoot的缩放类型,如果是PixelPerfect,Minimum Height和Maximum Height才起作用,换而言之,如果Scaling Style选择的是PixelPerfect就要对Minimum Height和Maximum Height进行设置。FixedSize和FixedSizeOnMobiles只跟Manual Height有关,区别在于后者(FixedSizeOnMobiles)只是针对IOS和Android上的判断,也就是说只有IOS和Android平台下FixedSizeOnMobiles才起作用。
& & & &那他们是怎么缩放的呢?如果是PixelPerfect缩放类型,当屏幕的分辨率大于Maximum Height,则以Maximum Height 为基础缩放,反之,如果屏幕分辨率小于Minimum Height 则以Minimum Height为基础进行缩放。例如,如果屏幕高度为1000,而设置的Maximum Height值为800,则UI界面整体放大为原来的.25倍。
& & & &如果Scaling Style指定为FixedSize或FixedSizeOnMobiles,则缩放只以Manual Height为参考,屏幕分辨率的高度值不同于此设置值时,则根据其比例(即Screen Height / Manual Height)对整棵UI树的进行“等比”缩放(宽度的缩放比也是此比例值)。
& & & 如果Scaling Style指定为FixedSize,UIWidget.height(以UIRoot默认进行高度缩放)是不会改变的(有关UIWidget的内容可以查看D.S.Qiu的另外一篇),不管实际屏幕分辨率的像素是多少,这看下Example 1 的 Anchor Stretch的背景图片,高度始终都是800,即设置的的manualHeight:
& & & & 也就是相当于UIRoot下的UIWidget的height参数一直都是实际的值,虽然在实际在显示器显示的高度不是UIWidget.height这个值,所以才有了放缩的感觉。实际的放缩是根据Camera.pixelHeight(这个值和Screen.height的大小是一样的)来的,也就是放缩比 = Camera.pixelHeight/UIRoot.manualHeight,或者是Screen.height/UIRoot.manualHeight。
& & & & &也就是说,当Scaling Style 指定为FixedSize,UIRoot的子对象高度的参数保持不变,至于显示的缩放是根据Camera自动进行的,程序无需额外控制。更多详细的分享可以参考另外一篇有关UIAnchor 和UIStretch的文章()。
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &增补于
Scaling Style策略 & & &&
(1)PixelPerfect和Minimum Height, Maximum Height
使用PixelPefect,只要是想达到UI图片尽可能不缩放,保持原尺寸大小,这种在PC端这种可以调节界面大小的会使用比较多。
(2)FixedSize和Manul Height
FixedSize只要是希望UI界面尽可能和屏幕分辨率适配,如移动设备上,特别是手机上,屏幕就那么小,UI界面一定要求全屏显示,就要进行缩放。
& & & &对于Unity实际开发中屏幕自适应问题,oneRain在①中有更详细的描述,这里只介绍下,D.S.Qiu想到的一种自适应策略——“花草”填充法。填充法(这个是D.S.Qiu命名的,哈哈,自恋下)指的是用其他图片区填充因为固定比例放缩而出现镂空黑边的区域,当然也可能已经有游戏是这么做的,当然oneRain说的增加一个宽度缩放比例,长宽分别以尽可能接近屏幕长宽比的比例去缩放。
Scale的实现
& & & &虽然我们已经了解了Scale的作用区别以及策略,那到底是怎么实现的呢?还是上代码:
void&Update&()&&&&&&{&&&&&&&&&&if&(mTrans&!=&null)&&&&&&&&&&{&&&&&&&&&&&&&&float&calcActiveHeight&=&activeH&&&&&&&&&&&&&&if&(calcActiveHeight&&&0f&)&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&float&size&=&2f&/&calcActiveH&&&&&&&&&&&&&&&&&&Vector3&ls&=&mTrans.localS&&&&&&&&&&&&&&&&&&&&&&&&if&(!(Mathf.Abs(ls.x&-&size)&&=&float.Epsilon)&||&&&&&&&&&&&&&&&&&&&&&&!(Mathf.Abs(ls.y&-&size)&&=&float.Epsilon)&||&&&&&&&&&&&&&&&&&&&&&&!(Mathf.Abs(ls.z&-&size)&&=&float.Epsilon))&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&mTrans.localScale&=&new&Vector3(size,&size,&size);&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&}&&&&&&&&&&}&&&&&&}&&
& & & &可以看出Update函数中是根据activeHeight来调整UIRoot的transform的localScale来实现的,哈,竟可以这么简单。那么,我们只要弄清楚activeHeight就可以了:
public&int&activeHeight&&&&&&{&&&&&&&&&&get&&&&&&&&&&{&&&&&&&&&&&&&&int&height&=&Mathf.Max(2,&Screen.height);&&&&&&&&&&&&&&if&(scalingStyle&==&Scaling.FixedSize)&return&manualH&&&#if&UNITY_IPHONE&||&UNITY_ANDROID&&&&&&&&&&&&&&if&(scalingStyle&==&Scaling.FixedSizeOnMobiles)&&&&&&&&&&&&&&&&&&return&manualH&&#endif&&&&&&&&&&&&&&if&(height&&&minimumHeight)&return&minimumH&&&&&&&&&&&&&&if&(height&&&maximumHeight)&return&maximumH&&&&&&&&&&&&&&return&&&&&&&&&&&}&&&&&&}&&
& & & &可以看出activeHeight就是前面Scale Style的不同参数的具体实现,即得到缩放参考高度。
Orthographic Size和分辨率
& & & &在上面Update和activeHeight的函数中都出现了 &“2” 这个常数,这个常数到底是怎么来的。要想知道这个,就要明白Camera 设定为Orthographic类型中的Size(即Orthographic Size)的含义,查看Unity文档,就可以知道这个Size是Camera看到区域的一半,如果Size设置为1,则Camera可以看到高度为为2的区域,然后我们知道照相机看到的区域是全画在整个屏幕的,也就是说Size的值对应为屏幕分辨率的一半。
& & & & 如果屏幕宽度为1000个像素,Size设置的值表示个像素。所以,我们通过整个关系计算UIRoot下的GameObject的实际对应屏幕的高度:从GameObject向上一直到UIRoot,将它们的loaclScal相乘得到的乘积除以Size乘以屏幕高度的一半,即(localScale*....localScale)/Size*Screen.height/2。
& & & & 这可以解释UIRoot的localStyle为啥都是很小的小数,因为这样可以保证UIRoot的子节点都可以以原来的大小作为localScale,比如一张图片是20*20的,我们可以直接设置localScale为(20,20,1)不用进行换算,直观方便。(NGUI3.0(or 2.7)以后的版本已经不再使用localScale来表示UISprite ,UILable(UIWidget的子类)的大小了,而是在UIWidget的width和height来设置,这样做的好处就是一个gameObject节点可以挂多个UISprite或UILabel了,而不会受localScale的冲突影响
& &增补)。
UIRoot细节
& & & 前面说道Update函数中有一个常数 2 ,表示Size是设置为1的,这个可以从Start函数就可以知道:
protected&virtual&void&Start&()&&&&&&{&&&&&&&&&&UIOrthoCamera&oc&=&GetComponentInChildren&UIOrthoCamera&();&&&&&&&&&&if&(oc&!=&null)&&&&&&&&&&{&&&&&&&&&&&&&&Debug.LogWarning(&UIRoot&should&not&be&active&at&the&same&time&as&UIOrthoCamera.&Disabling&UIOrthoCamera.&,&oc);&&&&&&&&&&&&&&Camera&cam&=&oc.gameObject.GetComponent&Camera&();&&&&&&&&&&&&&&oc.enabled&=&false;&&&&&&&&&&&&&&if&(cam&!=&null)&cam.orthographicSize&=&1f;&&&&&&&&&&}&&&&&&&&&&else&Update();&&&&&&}&&
& & & 但是这里似乎有点疏忽,这里只移除UIOrthoCamera这个脚本(UIRoot脚本开始就言明这两个脚本不能同时使用,所以要移除),并将cam的orthographicSize设置为1f,但是我想如果没有UIorthoCamera这个脚本的话,就不会重新设置Camera的orthographicSize值,这样如果orthographicSize不是1的话,效果就不一样了。刚开始我会以为这是NGUI developer的一个Bug,但是如果都在Start设置orthographicSize为1f,那这个参数就没有意义了,让使用者自己设置可以有更多效果,如“屏中屏”——将满屏的UI缩放为另外一个UI界面的一半大小,所以才会说“似乎有点疏忽”。
& & & 下面看下效果图:
orthographicSize=1
&orthographicSize=2
& & & & 很明显可以orthographicSize=2时,图片进行了缩小。当orthographicSize=1时背景图片用了UIStretch脚本来实现满屏效果,当orthographicSize为2时却没有满屏,这就说明代码中UIRoot是以2为屏幕宽度的,现在Camera的视野大小为4,那映射到屏幕当然不会有“满屏”的效果了(只会是屏幕宽度的一半),背景图片在左上角是因为使用UIAnchor脚本。
& & & & &②和③中分别都介绍了如何设置Orthographic Size来达到像素和Unity中单位对应起来,都写的很不错,这也是我写这篇博客的一个触动。
& & & & &UIRoot中还有两类函数:GetPixelSizeAdjustment 和&Broadcast,前者是获取当前分辨率的单个像素的大小,而后者其实就一个UIRoot的消息广播函数,还有一个当前激活状态下的UIRoot的队列。至此D.S.Qiu已经将UIRoot脚本解析的淋漓尽致了,自然就剩下小结了。
『基于宽度放缩
& & & & UIRoot是基于高度放缩的,即放缩的比例是以高度为参考的,所以UIRoot有一个manualHeight的参数。那么对于横版游戏显然不行,要是能实现基于宽度放缩。所以可以通过设置一个“manualWidth”的参数来做。比如我们项目中使用的是 1024 作为UI的宽屏尺寸,通过换算设置manualHeight的值:
int&height&=&Mathf.Max(2,&Screen.height);&&manualHeight&=&Screen.height&*&1024&/&Screen.&&&
& & & & 之前的同事用了很多方法都没有搞定,其实根本就没有那么复杂,所以一旦知道原理之后,很多事情就变得简单多了。
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &增补于 & & & & & & & 22:14
& & & & 一直都想把NGUI的内部机制彻底的弄明白,一直都没付诸实践,知道看②和③中的文章,D.S.Qiu发现还是有必要尽快整理下,切好最近项目没什么事情,也是周末。UIRoot这个脚本虽然很简单,但确实NGUI整个体系的基石。更多点击查看。
& & & &&如果您对D.S.Qiu有任何建议或意见可以在文章后面评论,或者发邮件(gd.s.)交流,您的鼓励和支持是我前进的动力,希望能有更多更好的分享。
& & & & 转载请在文首注明出处:/blog/1964679
更多精彩请关注D.S.Qiu的和微博(ID:静水逐风)
②风宇冲:&
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:52201次
排名:千里之外
原创:23篇
转载:161篇
(3)(1)(5)(3)(8)(4)(4)(3)(10)(11)(1)(3)(6)(12)(18)(14)(3)(4)(3)(4)(14)(20)(5)(2)(6)(7)(10)小站会根据您的关注,为您发现更多,
看到喜欢的小站就马上关注吧!
下一站,你会遇见谁的梦想?
只有偏执狂才可能生存
(客户端unity)实现对玩家注册信息的提交
using UnityE
using System.C
public class PlayerRegist : MonoBehaviour {
& & public string URL = "http://localhost/UnitySever/regist.php";
& & public UIInput playerN
& & public UIInput playerP
& & public UIInput playerPwdE
& & private string LoginSence = "LoginSence";
& & private GameObject messageB
& & void Start()
& & & & GameObject btnSubmit = GameObject.Find("UI Root (2D)/Camera/Anchor/Panel/BTNSubmit");
& & & & GameObject btnBack = GameObject.Find("UI Root (2D)/Camera/Anchor/Panel/BTNBack");
& & & & UIEventListener.Get(btnSubmit).onClick = BtnSubmitC
& & & & UIEventListener.Get(btnBack).onClick = BtnBackC
& & void BtnSubmitClick(GameObject btnSubmit)
& & & & StartCoroutine(Regist());
& & void BtnBackClick(GameObject btnBack)
& & & & Application.LoadLevel(LoginSence);
& & void BtnCloseClick(GameObject btnClose)
& & & & Destroy(messageBox);
& & IEnumerator Regist()
& & & & WWWForm form = new WWWForm();
& & & & form.AddField("playerName", playerName.text);
& & & & form.AddField("playerPwd", playerPwd.text);
& & & & form.AddField("playerPwdEnsure", playerPwdEnsure.text);
& & & & WWW www = new WWW(URL, form);
& & & & if (www.error != null)
& & & & & & Debug.Log(www.error);
& & & & else
& & & & & & string returnText = www.
& & & & & & if (returnText == "REGIST_SUCCEED")
& & & & & & {
& & & & & & & & Debug.Log(www.text);
& & & & & & & & MessageBoxShow("注册成功",37,-32,-10);
& & & & & & &
& & & & & & }
& & & & & & else if (returnText == "PLAYER_EXIST")
& & & & & & {
& & & & & & & & Debug.Log(www.text);
& & & & & & & & MessageBoxShow("该用户已存在", 37, -32, -10);
& & & & & & }
& & & & & & else if(returnText=="INFO_NULL")
& & & & & & {
& & & & & & & & Debug.Log(www.text);
& & & & & & & & MessageBoxShow("用户名或密码不能为空", 37, -32, -10);
& & & & & & }
& & & & & & else if (returnText == "ENSURE_FAILED")
& & & & & & {
& & & & & & & & Debug.Log(www.text);
& & & & & & & & MessageBoxShow("两次密码输入不一致", 37, -32, -10);
& & & & & & }
& & & & & & else
& & & & & & {
& & & & & & & & Debug.Log(www.text);
& & & & & & & & MessageBoxShow("注册出现异常", 37, -32, -10);
& & & & & & }
& & & & playerName.text = "";
& & & & playerPwd.text = "";
& & void MessageBoxShow(string Information, float messagebox_X, float messagebox_Y, float messagebox_Z)
& & & & //得到预制并动态创建&
& & & & messageBox = (GameObject)Instantiate(Resources.Load("MessageBox"));
& & & & //加入到Anchor层级下
& & & & messageBox.transform.parent = GameObject.Find("UI Root (2D)/Camera/Anchor").
& & & & GameObject lbMessage = GameObject.Find("UI Root (2D)/Camera/Anchor/MessageBox(Clone)/Label");
& & & & UILabel label = lbMessage.GetComponent&UILabel&();
& & & & //设置提示信息
& & & & label.text = I
& & & & //局部平移信息
& & & & messageBox.transform.localPosition = new Vector3(messagebox_X, messagebox_Y, messagebox_Z);
& & & & //局部缩放信息
& & & & messageBox.transform.localScale = new Vector3(1, 1, 1);
& & & & GameObject btnClose = GameObject.Find("UI Root (2D)/Camera/Anchor/MessageBox(Clone)/BTNClose");
& & & & UIEventListener.Get(btnClose).onClick = BtnCloseC
(客户端unity)实现对玩家登陆信息的验证
using UnityE
using System.C
public class PlayerLogin : MonoBehaviour {
& & public string URL = "http://localhost/UnitySever/login.php";
& & public UIInput playerN
& & public UIInput playerP
& & private string GameSence = "GameSence";
& & private string registSence = "RegistSence";
& & private GameObject messageB
void Start () {
& & & & GameObject btnLogin = GameObject.Find("UI Root (2D)/Camera/Anchor/Panel/BTNLogin");
& & & & GameObject btnRegist = GameObject.Find("UI Root (2D)/Camera/Anchor/Panel/BTNRegist");
& & & & UIEventListener.Get(btnLogin).onClick = BtnLoginC
& & & & UIEventListener.Get(btnRegist).onClick = BtnRegistC
& & void BtnLoginClick(GameObject btnPlay)
& & & & StartCoroutine(Login());
& & void BtnRegistClick(GameObject btnPlay)
& & & & Application.LoadLevel(registSence);
& & void BtnCloseClick(GameObject btnClose)
& & & & Destroy(messageBox);
& & IEnumerator Login()
& & & & //获取Input中的值
& & & & WWWForm form = new WWWForm();
& & & & form.AddField("playerName", playerName.text);
& & & & form.AddField("playerPwd", playerPwd.text);
& & & & WWW www = new WWW(URL, form);
& & & & if (www.error != null)//下载失败
& & & & & & Debug.Log(www.error);
& & & & else
& & & & & & string returnText = www.//text的值即为echo的值
& & & & & & if (returnText == "CHECK_SUCCEED")//验证成功
& & & & & & {
& & & & & & & & Debug.Log(www.text);
& & & & & & & & Application.LoadLevel(GameSence);
& & & & & & }
& & & & & & else if (returnText == "INFO_NULL")//玩家名或密码为空
& & & & & & {
& & & & & & & & Debug.Log(www.text);
& & & & & & & & MessageBoxShow("用户名或密码不能为空", 0, -100, -10);
& & & & & & }
& & & & & & else if (returnText == "PLAYER_NO_EXIST")//用户不存在
& & & & & & {
& & & & & & & & Debug.Log(www.text);
& & & & & & & & MessageBoxShow("该用户不存在", 0, -100, -10);
& & & & & & }
& & & & & & else if (returnText == "PWD_INCORRECT")//密码不正确
& & & & & & {
& & & & & & & & Debug.Log(www.text);
& & & & & & & & MessageBoxShow("您输入的密码有误", 0, -100, -10);
& & & & & & }
& & & & & & www.Dispose();
& & & & //清空Input
& & & & playerName.text = "";
& & & & playerPwd.text = "";
& & void MessageBoxShow(string Information,float messagebox_X,float messagebox_Y,float messagebox_Z)
& & & & //得到预制并动态创建&
& & & & messageBox = (GameObject)Instantiate(Resources.Load("MessageBox"));
& & & & //加入到Anchor层级下
& & & & messageBox.transform.parent = GameObject.Find("UI Root (2D)/Camera/Anchor").
& & & & GameObject lbMessage = GameObject.Find("UI Root (2D)/Camera/Anchor/MessageBox(Clone)/Label");
& & & & UILabel label = lbMessage.GetComponent&UILabel&();
& & & & //设置提示信息
& & & & label.text = I
& & & & //局部平移信息
& & & & messageBox.transform.localPosition = new Vector3(messagebox_X, messagebox_Y, messagebox_Z);
& & & & //局部缩放信息
& & & & messageBox.transform.localScale = new Vector3(1, 1, 1);
& & & & GameObject btnClose = GameObject.Find("UI Root (2D)/Camera/Anchor/MessageBox(Clone)/BTNClose");
& & & & UIEventListener.Get(btnClose).onClick = BtnCloseC
(服务器端)实现对玩家注册信息的提交
/*实现对玩家注册信息的提交*/
/*后台信息*/
$host="localhost";
$user="root";
$user_pwd="1314";
$db_name="GAME";
/*数据库连接*/
mysql_connect($host,$user,$user_pwd)or die("Cant Connect The DataBase!");
mysql_select_db($db_name)or die("Cant Connnect The DataBase!");
/*玩家信息*/
$player_name=$_POST['playerName'];
$player_pwd=$_POST['playerPwd'];
$player_pwd_ensure=$_POST['playerPwdEnsure'];
/*查表返回资源集*/
$str_select="SELECT * FROM PLAYER_INFO WHERE PLAYER_NAME='".$player_name."'";
$result_select=mysql_query($str_select);
$row_select=mysql_num_rows($result_select);
/*注册用户*/
if(!$player_name||!$player_pwd)
echo "INFO_NULL";//玩家名或密码为空
else if($row_select)
echo "PLAYER_EXIST";//玩家已存在
if(!strcmp($player_pwd,$player_pwd_ensure))
$str_insert="INSERT INTO PLAYER_INFO (PLAYER_NAME,PLAYER_PWD) VALUES ('".$player_name."','".$player_pwd."')";
$result_insert=mysql_query($str_insert);
if($result_insert)
echo "REGIST_SUCCEED";//注册成功
echo "REGIST_FAILED";//注册异常
echo "ENSURE_FAILED";//两次密码输入不一致
/*关闭数据库连接*/
mysql_close();
(服务器端)实现对玩家登陆信息的验证
/*实现对玩家登陆信息的验证*/
/*后台信息*/
$host="localhost";
$user="root";
$user_pwd="1314";
$db_name="GAME";
/*数据库连接*/
mysql_connect($host,$user,$user_pwd)or die("Cant Connect The DataBase!");
mysql_select_db($db_name)or die("Cant Connnect The DataBase!");
/*玩家信息*/
$player_name=$_POST['playerName'];
$player_pwd=$_POST['playerPwd'];
/*查表返回资源集*/
$str_select="SELECT * FROM PLAYER_INFO WHERE PLAYER_NAME='".$player_name."'";
$result_select=mysql_query($str_select);
$row_select=mysql_num_rows($result_select);
/*验证用户*/
if(!$player_name||!$player_pwd)
echo "INFO_NULL";//玩家名或密码为空
$str_select="SELECT * FROM PLAYER_INFO WHERE PLAYER_NAME='".$player_name."'";
$result_select=mysql_query($str_select);
$row_select=mysql_num_rows($result_select);
if(!$row_select)
echo "PLAYER_NO_EXIST";//玩家不存在
$datas=mysql_fetch_array($result_select);
if(!strcmp($player_pwd,$datas["PLAYER_PWD"]))
echo "CHECK_SUCCEED";//验证成功
echo "PWD_INCORRECT";//密码不正确
/*关闭数据库连接*/
mysql_close();
站长在关注unity3d游戏开发之UIRoot_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
unity3d游戏开发之UIRoot
上传于|0|0|文档简介
&&unity3d游戏开发之UIRoot
阅读已结束,如果下载本文需要使用0下载券
想免费下载更多文档?
定制HR最喜欢的简历
你可能喜欢46818人阅读
Unity3D开发(8)
NGUI在Unity3D游戏开发中非常常用,而NGUI对于每一个UI场景,都是以一个UIRoot为UI游戏对象树的根的,那么这个UIRoot是起什么作用的呢?
先简单看一下UIRoot中的基本属性
UIRoot游戏对象的属性只有4个,分别是缩放规则,手动高度,最小高度和最大高度
而正是这4个属性,将影响整个UI场景中整体的缩放比例,当设置好这4个属性之后,UIRoot游戏对象的相对缩放值(LocalScale)将会生成并且不能被直接修改(NGUI中很多属性都是不能直接被修改的,这种控制是在UIRoot脚本中,通过设置[ExecuteInEditMode]做到的,其相对缩放值是根据UIRoot的4个属性计算出来的),那么这4个属性分别是什么含义呢?
(吐槽一下,也许这里的用户体验并不足够友好,因为Manual Height和Minimum Height, Maximum Height并不会同时起作用,如果能做到在选择Scaling Style时动态的切换,使用者也许能更清楚它们之间的关系)
<span style="color:#.Scaling Style (缩放类型)
这是一个简单的枚举变量,包括三个枚举&#20540;
public enum Scaling
PixelPerfect,
FixedSize,
FixedSizeOnMobiles,
(FixedSize和FixedSizeOnMobiles类&#20284;,并且后者只添加了对ios和android平台的判断,所以前者可以替代后者使用)
这里只讨论PixelPerfect和FixedSize的区别,两者都是针对于所有在此UIRoot之下的UI组件而言的,也可以认为是在此UIRoot下,整个游戏屏幕的尺寸的缩放类型!
<span style="color:#.Manual Height和Minimum Height, Maximum Height (手动高度和最小高度,最大高度)
Manual Height和Minimum Height, Maximum Height不会同时对此UIRoot起作用,当选择Scaling Style为PixelPerfect时,我们需要设置Minimum Height, Maximum Height;而当Scaling Style为FixedSize或FixedSizeOnMobiles时,我们需要设置Manual Height。(这就是我前面吐槽的原因)
<span style="color:#.使用
(1)PexelPerfect和Minimum Height, Maximum Height
这个组合主要用于我们期望所有的UI纹理都“尽量”不进行缩放,所谓“尽量”的程度,则是取决于Minimum Height和Maximum Height,Minimum Height表示当设备分别率小于此设置&#20540;时,根据此设置&#20540;对UIRoot进行缩放;Maximum Height表示当设备分辨率大于此设置&#20540;时,根据此设置&#20540;对UIRoot进行缩放(UIRoot是UI游戏对象树的根,修改UIRoot的缩放,则会影响整棵UI树的缩放)
(2)FixedSize和Manul Height
这个组合主要用于我们期望所有的UI纹理都进行“合适”的缩放,所谓“合适”缩放的原则,则是根据Manual Height设置&#20540;,当设备分辨率的高度&#20540;不同于此设置&#20540;时,则根据其比例(即Manual Height /&Screen Height)对整棵UI树的进行“等比”缩放(宽度的缩放比也是此比例&#20540;),这样,我们就可以做一套资源,在不同尺寸的分辨率最好的“不变形”的适配了
前面两组在什么情况下等同呢?
Manual Height == Minimum Height == Maximum Height&
推导过程,呵呵~~
具体可参考UIRoot中activeHeight属性和GetPixelSizeAdjustment的计算过程
<span style="color:#.这也许并不够
基于以上推到,当我们以为标准分辨率做一套UI资源(也就是选择FixedSize并且Manual Height=768),&#20284;乎可以满足百分之90以上的机型了,而为什么是呢?
既然我们已经容忍在除之外的其他设备上进行等比缩放了,那为什么不是960x640呢?
计算一下的宽高比=1.33,960x640的宽高比=1.5,这就是移动设备的分辨率比例的全部了吗?
当然不是,iphone5的比例就要大于1.5,还有各种奇葩的android设备呢,比如夏新的n828就是960x540,宽高比=1.78
那为什么以为标准呢?
因为1.33的宽高比,当我们的的资源到960x640的设备上时会有什么现象?
根据Manual Height / Screen Height的比例可知,我们需要缩放768 / 640 = 1.2倍,假设是一张的纹理,高度缩放1.2倍变为了640,宽度也要相应缩放1.2倍变为853(保证等比缩放不变形),也就是说的资源放到960x640上反而两边有了黑边,这是我们可以容忍的,我们可以做一个很大的背景或者拉伸,保证UI组件不变形即可,很多游戏都是这么做的,比如植物大战僵尸在iphone5和ipad上看到的背景视野并不一样大!
当放到夏新的机器上呢?
我们需要缩放768 / 540 = 1.4倍,宽度1024 / 1.4 = 731,这是可以的,只是看起来更怪一些,因为两边的黑边相对比例更大了(960 - 731=229的黑边区域)
而我表示android机器的分辨率奇葩到只有想不到,没有做不到的程度,也许宽高比1.7并不是终点,当遇到1.8之后,黑边的相对比例会更大。。。
<span style="color:#.问题又来了
假设我们的游戏类型更适合iphone手机玩,不太适合ipad,所以我希望能以960x640为标准做一套资源,可以吗?
我只能说不太可以,因为你要在设计UI组件的大小做限制了,为什么需要做限制?
假设我有一张纹理是960x640大小的,在iphone上铺满整屏,根据我们的设置(FixedSize和Manual Height=640),拿到的分辨率上,高度640 / 768 = 0.83,为了保证等比缩放,宽度960 / 0.83 = 1156,不幸的事情发生了,1156 & 1024,这个UI组件宽度超过了屏幕的宽度,被裁剪了。。。这是我们不能容忍的,或许你可以说我们尽量不做这种尺寸的UI,OK,你可以对UI尺寸加限制,但是当面对android那些奇葩的分辨率的时候,你会发现限制越来越大,这也许会让美术和策划疯掉!
<span style="color:#.解决方案
当我们花上一些时间去观察现在移动设备的分辨率时,虽然奇葩很多,但是还是有一些规律的,规律的在于宽高比而不在于具体尺寸,大体上划分一下宽高比在1.3,1.5,1.7的范围上的居多(基本是全部吧!)即便是再有1.2,1.8的比例也无妨。。。
NGUI为我们提供的方案只有以各种高度为衡量标准是不够的,我们应该加上一种以宽度为衡量标准的缩放类型
而对于UI资源的标准,我们选取960x640,宽高比为1.5
这样,当我们在兼容大于1.5的尺寸的时候,使用NGUI的现有方案;当我们在兼容小于1.5的尺寸的时候,使用以宽度为衡量标准
也就是说有一个类&#20284;Manual Width的属性,当小于1.5时,我们使用Manual Width / Screen Width得出整棵UI树的缩放比例!
这样做的好处是“黑边”区域不会太大,并且不需要对UI组件的大小做限制!
PS: 我表示以上言论对于“可以为适配分辨率做无数套图的资源土豪”而言可能是我想多了!
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:861098次
积分:8061
积分:8061
排名:第2034名
原创:70篇
转载:23篇
评论:399条
阅读:222458
文章:27篇
阅读:367267
(3)(1)(3)(2)(1)(5)(1)(2)(4)(3)(2)(5)(4)(4)(5)(5)(6)(4)(2)(8)(2)(1)(2)(3)(6)(2)(1)(1)(2)(3)}

我要回帖

更多关于 unity3d uiroot 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信