NGUI所见即所得之UIAnchor & UIStretch - 推酷
NGUI所见即所得之UIAnchor & UIStretch
& & & &NGUI的Example/Scenes/Example1介绍的主要就是UIRoot,UIAnchor和UIStretch这三个脚本,当然UIRoot是每个UI都会有的(挂在根节点),之前D.S.Qiu也写过博客介绍过UIRoot(猛点查看)。一直都对NGUI把Unity的单位和像素的转换和统一都很有疑惑,因之手游项目要做UI的自适应,就觉得很有必要把UIAnchor和UIStretch深入的研究下。
& & & & UIRoot在D.S.Qiu的第一篇NGUI的文章中介绍了(猛点查看),UIRoot其实就做了一件事情:根据Screen.height和UIRoot.activeHeight的比例来调整UIRoot的loaclScal,从而保证UIWidget(UISprite,UILabel)可以按照其本身的大小进行设置,而不用经过复杂的换算过程。
& & & & &UIAnchor和UIStretch处理上的细节很相似,都是先计算参照对象(这个参照对象由Insprector的Container指定,如果没有选择,就是Camera)的大小Rect,然后根据参数UIAnchor(Side,relativeOffset,pixelOffset),UIStretch(Style,relativeSize,initialSize,borderPadding)进行调整,最后设置对应的属性,只不过UIAnchor设置的是transform.position,UIStretch设置的是(width,height)或clipRange等。
& & & & 先看下UIAnchor的Inspector界面,感觉很简单,不会像UIPanel那么复杂:
& & & & Container:指定Anchor的参照点,如果没有选择,则以Camera的pixelRect的区域为参照面
& & & & Side:Anchor的定位方式
& & & & Relative Offset:相对于Camera,或Container的百分比偏移
& & & & Pixel Offset:像素的偏移
/// &summary&
/// Relative offset value, if any. For example &0.25& with 'side' set to Left, means 25% from the left side.
/// &/summary&
public Vector2 relativeOffset = Vector2.
/// &summary&
/// Pixel offset value if any. For example &10& in x will move the widget 10 pixels to the right
/// while &-10& in x is 10 pixels to the left based on the pixel values set in UIRoot.
/// &/summary&
public Vector2 pixelOffset = Vector2.
&Update函数
& & & &UIAnchor的主要功能实现都在Update函数:
void Update ()
if (mAnim != null && mAnim.enabled && mAnim.isPlaying)
bool useCamera =
UIWidget wc = (container == null) ? null : container.GetComponent&UIWidget&();
UIPanel pc = (container == null && wc == null) ? null : container.GetComponent&UIPanel&();
if (wc != null)
Bounds b = wc.CalculateBounds(container.transform.parent);
mRect.x = b.min.x;
mRect.y = b.min.y;
mRect.width = b.size.x;
mRect.height = b.size.y;
else if (pc != null)
if (pc.clipping == UIDrawCall.Clipping.None)
// Panel has no clipping -- just use the screen's dimensions
float ratio = (mRoot != null) ? (float)mRoot.activeHeight / Screen.height * 0.5f : 0.5f;
mRect.xMin = -Screen.width *
mRect.yMin = -Screen.height *
mRect.xMax = -mRect.xM
mRect.yMax = -mRect.yM
// Panel has clipping -- use it as the mRect
Vector4 pos = pc.clipR
mRect.x = pos.x - (pos.z * 0.5f);
mRect.y = pos.y - (pos.w * 0.5f);
mRect.width = pos.z;
mRect.height = pos.w;
else if (container != null)
Transform root = container.transform.
Bounds b = (root != null) ? NGUIMath.CalculateRelativeWidgetBounds(root, container.transform) :
NGUIMath.CalculateRelativeWidgetBounds(container.transform);
mRect.x = b.min.x;
mRect.y = b.min.y;
mRect.width = b.size.x;
mRect.height = b.size.y;
else if (uiCamera != null)
useCamera =
mRect = uiCamera.pixelR
float cx = (mRect.xMin + mRect.xMax) * 0.5f;
float cy = (mRect.yMin + mRect.yMax) * 0.5f;
Vector3 v = new Vector3(cx, cy, 0f);
if (side != Side.Center)
if (side == Side.Right || side == Side.TopRight || side == Side.BottomRight) v.x = mRect.xM
else if (side == Side.Top || side == Side.Center || side == Side.Bottom) v.x =
else v.x = mRect.xM
if (side == Side.Top || side == Side.TopRight || side == Side.TopLeft) v.y = mRect.yM
else if (side == Side.Left || side == Side.Center || side == Side.Right) v.y =
else v.y = mRect.yM
float width = mRect.
float height = mRect.
v.x += pixelOffset.x + relativeOffset.x *
v.y += pixelOffset.y + relativeOffset.y *
if (useCamera)
if (uiCamera.orthographic)
v.x = Mathf.Round(v.x);
v.y = Mathf.Round(v.y);
if (halfPixelOffset && mNeedsHalfPixelOffset)
v.x -= 0.5f;
v.y += 0.5f;
v.z = uiCamera.WorldToScreenPoint(mTrans.position).z;
v = uiCamera.ScreenToWorldPoint(v);
v.x = Mathf.Round(v.x);
v.y = Mathf.Round(v.y);
if (pc != null)
v = pc.cachedTransform.TransformPoint(v);
else if (container != null)
Transform t = container.transform.
if (t != null) v = t.TransformPoint(v);
v.z = mTrans.position.z;
// Wrapped in an 'if' so the scene doesn't get marked as 'edited' every frame
if (mTrans.position != v) mTrans.position =
if (runOnlyOnce && Application.isPlaying) Destroy(this);
& & & &Update的原理很简单,梳理归纳为4部分:
& & & & & & & & &1)获取Anchor参照对象的大小Rect以及计算中心点Vector3 v;
& & & & & & & & &2)根据Side类型调整v的x,y,z值;
& & & & & & & & &3)将v转换成世界坐标
& & & & & & & & &4)将v赋给mTrans.position。
& & & & 这里对1)再多说几句,主要是涉及参照对象的选取问题,用if - else if来筛选的次序是 UIWidget wc , UIPanel pc , GameObject container, Camera uiCamera,如果前者部位null这取前者的大小后面的就不予考虑。
UIWidget wc = (container == null) ? null : container.GetComponent&UIWidget&();
UIPanel pc = (container == null && wc == null) ? null : container.GetComponent&UIPanel&();
像素与Unity单位
& & & & 之前项目中使用的NGUI版本还是2.6.3,那个版本还没有pixelOffset,然后为了实现一个相对便宜就在挂载Anchor的对象下面挂载一个子对象,通过设置子对象的loaclPosition来设置相对偏移:
& & & 这样用transform.find去查找某一个子对象的时候就会觉得很蛋疼,所以当看到pixelOffset的就觉得没有必要用offset这层节点了,然后果断测试就会有以下不同的情况。
& & & 测试之前首先将上面Bottom/Offset的localPosition置0,并修改稿Bottom的UIAnchor的pixelOffset改为(0,40)
1)当参照对象是Camera时,即Container=null:
但当编辑器的分辨率等于某个值时,又回恢复正常情况:
2)把Bottom的父对象UIPanel拖给UIAnchor的Container:
这种情况是没有问题的:
& & & &回过头看下Update函数中对pixelOffset的使用:
v.x += pixelOffset.x + relativeOffset.x *
v.y += pixelOffset.y + relativeOffset.y *
&& & & &经过反复的思考,觉得一定是pixelOffset和子对象Offset的localPosition数值的参考系是不一样的,但最终都是通过mRect来处理的,所以把UIAnchor Rect mRect设置成public,查看mRect的值,上面三个情况对应mRect值分别如下:
& & & 这说明,当mRect.y大于等于800的时候,使用UIAnchor的pixelOffset和使用子对象Offset的localPosition的表现是一致的。但为什么指定Container为UIPanel都不会出现异常情况,只有Camera会出现。再回到Update看下获取mRect的方法,指定Container时,mRect实际是UIPanel,或UIWideget的像素大小,其实是UIWidget的(width,height),而没有指定Container情况下,mRect = camera.pixelRect。
& & & 在UIRoot文中,就说过camera.pixelRect其实就是Screen的(width,height),也就是说,camera.pixelRect是会根据显示器的分辨率动态改变的,而指定Container时,mRect是不会改变的(在介绍UIRoot文中有介绍)。
& & & &在看下pixelOffset的使用(真的是最后一次了):
v.x += pixelOffset.x + relativeOffset.x *
v.y += pixelOffset.y + relativeOffset.y *
& & & &虽然pixelOffset的值一直没有变化,但是当mRect = camera.pixelCamera时,mRect是随着分辨率的变化而变化的,那样的话pixelOffset占的权重就会改变了,所以才会出现上面的偏移异常。
& & & & 还有一个问题:为什么当camera.pixelRect.y等于800时,就会恢复正常,这个先看下UIRoot的设置(对UIRoot原理不了解请猛击):
& & & & Manual Height设置为800,Scaling Style设置为FixedSize,可以知道UI的放缩参考高度就是 800,即实际UI布局高度就是800,这里有点难理解,总之就是当屏幕分辨率高度等于800时,pixelOffset和子对象Offset的localPostion参考点就一致了,实际效果就一样了。也可以这么解释:当mRect = camera.pixelRect 时,pixeloffset的值是相对于camera.pixelRect而言的,在屏幕的呈现是会对着屏蔽的分辨率不同而改变的;而使用子对象Offset的localPosition的参照和UI组件是一致的,所以相对于Contaner的位置是不会改变的。
& & & & 回到文中开头抛出的一个问题----Unity中transfrom的单位和像素的关系,上张图片,可以知道UI的高度实际高度是800,然后看下Anchor - Top 和Anchor - Bottom的transform的localPostion.y分别是400.5006和-399.4994(图片如下),发现两者区间刚好是800,这就说明NGUI的架构中像素坐标和Unity的单位是一致的,对等的,即一个Unity单位等于一个像素。
& & & &看下NGUI Example1 的Anchor - Stretch的Inspector面板,发现UIStretch只比UIAnchor多了一个参数,不过从这张图UISprite的Dimension(红框标出)的长度始终都是800,不管屏幕如何改变大小,都是800个像素,填充的Tiled图片个数也是一样的,这也更加说明了上面提到的一个结论:NGUI中Unity的单位和像素是同一的。
& & & &UIStretch的Update函数的前面部分跟UIAnchor的Update的前面部分原理是一样的都是获取mRect,所以只看后一部分的实现:
void Update()
//.......省略上面的处理
float rectWidth = mRect.
float rectHeight = mRect.
if (adjustment != 1f && rectHeight & 1f)
float scale = mRoot.activeHeight / rectH
rectWidth *=
rectHeight *=
Vector3 size = (mWidget != null) ? new Vector3(mWidget.width, mWidget.height) : mTrans.localS
if (style == Style.BasedOnHeight)
size.x = relativeSize.x * rectH
size.y = relativeSize.y * rectH
else if (style == Style.FillKeepingRatio)
// Contributed by Dylan Ryan
float screenRatio = rectWidth / rectH
float imageRatio = initialSize.x / initialSize.y;
if (imageRatio & screenRatio)
// Fit horizontally
float scale = rectWidth / initialSize.x;
size.x = rectW
size.y = initialSize.y *
// Fit vertically
float scale = rectHeight / initialSize.y;
size.x = initialSize.x *
size.y = rectH
else if (style == Style.FitInternalKeepingRatio)
// Contributed by Dylan Ryan
float screenRatio = rectWidth / rectH
float imageRatio = initialSize.x / initialSize.y;
if (imageRatio & screenRatio)
// Fit horizontally
float scale = rectWidth / initialSize.x;
size.x = rectW
size.y = initialSize.y *
// Fit vertically
float scale = rectHeight / initialSize.y;
size.x = initialSize.x *
size.y = rectH
if (style != Style.Vertical)
size.x = relativeSize.x * rectW
if (style != Style.Horizontal)
size.y = relativeSize.y * rectH
if (mSprite != null)
float multiplier = (mSprite.atlas != null) ? mSprite.atlas.pixelSize : 1f;
size.x -= borderPadding.x *
size.y -= borderPadding.y *
if (style != Style.Vertical)
mSprite.width = Mathf.RoundToInt(size.x);
if (style != Style.Horizontal)
mSprite.height = Mathf.RoundToInt(size.y);
size = Vector3.
else if (mWidget != null)
if (style != Style.Vertical)
mWidget.width = Mathf.RoundToInt(size.x - borderPadding.x);
if (style != Style.Horizontal)
mWidget.height = Mathf.RoundToInt(size.y - borderPadding.y);
size = Vector3.
else if (mPanel != null)
Vector4 cr = mPanel.clipR
if (style != Style.Vertical)
cr.z = size.x - borderPadding.x;
if (style != Style.Horizontal)
cr.w = size.y - borderPadding.y;
mPanel.clipRange =
size = Vector3.
if (style != Style.Vertical)
size.x -= borderPadding.x;
if (style != Style.Horizontal)
size.y -= borderPadding.y;
if (mTrans.localScale != size)
mTrans.localScale =
if (runOnlyOnce && Application.isPlaying) Destroy(this);
& & & &本来昨天晚上就想写的,但是由于心情不好,也还要一些要点没有相同,所以才拖到现在完成,今天上了半天班(虽然一直都是在NBA的,今天的詹姆斯太牛逼了,看到我心情都好了,18投14中,罚球11中10,39分),有点小不敬业,吃完中饭之后,就开始组织些了,一直写到现在(花了5个小时),截了好些图,这篇应该是D.S.Qiu这么多篇中写得最畅快最爽的一次,解决之前的疑问。
& & & &和UIRoot一样,UIAnchor和UIStretch很简单,但是却很重要,虽然就几个参数,但是要完全明白和理解还是需要花点时间的,所以我才写出来跟大家分享的,NGUI的文章页写了几篇了(点击查看),转载注明出处,尊重原创。
& & & & 如果您对D.S.Qiu有任何建议或意见可以在文章后面评论,或者发邮件(gd.s.)交流,您的鼓励和支持是我前进的动力,希望能有更多更好的分享。
& & & & 转载请在文首注明出处:/blog/1975972
更多精彩请关注D.S.Qiu的博客和微博(ID:静水逐风)&
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致扫一扫,访问微社区
后使用快捷导航没有帐号?
签到成功!您今天第{todayrank}个签到,签到排名竞争激烈,记得每天都来签到哦!已连续签到:{constant}天,累计签到:{days}天
Unity-NGUI-UIRoot
|个人分类:|
1、作用负责管理UI的缩放,由于widget的坐标通常由像素决定,一个800x400的widget将占据800x400的图形单位,这个是非常大的,UIRoot通过颠倒屏幕的高度来收缩自己,以此来保持widget更小并更容易使用!2、UIRoot有三个缩放风格可供选择a、PixelPerfect (完美像素,点对点)在这种模式下,widget以实际大小占据屏幕大小,UI将始终以像素为单位,一个300x200的widget将始终在屏幕上以300x200的像素显示,这意味着,在低分辨率的设备上,你的UI将显示的非常大,反之,在高分辨率的设备上,你的UI将显示的非常小,从好的方面说,使用这个设置你的UI将不会被缩放,从而也就避免造成UI纹理失真,而会一直保持UI纹理清晰!b、FixedSize(固定尺寸)与PixelPerfect正好相反,widget以百分比的形式占据屏幕的大小,当你选择了这个设置后,对于NGUI而言,你的屏幕将永远是这不变的尺寸!不管屏幕实际的大小,这意味着一个300x200的widget将占一个分辨率为屏幕的25%,当你把你的分辨率降到,他也仍然占25%,如果你并不关心你的UI在不同尺寸的屏幕上展示的效果如何,也不关心他是否展示的足够清晰(因为会被缩放),选择这个设置,但是选择这一项时不要忘记设置Manual Height!c、FixedSizeonMobile(在手机上固定尺寸)是上面两个的组合,他表现的好像这个设置是“PixelPerfect”在桌面上建立的一样,当目标针对的是手机平台的话,如果这个尺寸是“FixedSize”,那么他将起作用!如果你不选择FixedSize选项,那么不要忘记设置Minimum和Maximum Height的值,这些值被用于保持你的虚拟屏幕尺寸在“理智”的价值观中,例如如果你的UI被设置成PixelPerfect模式,并且Minimum Height被设置成720,当一些玩家尝试去运行你的应用程序使用的是800x600像素,UI将会表现的好像这个设置是Fixed Size,并且Manual Height被设置成7203、Shrink Portrait (缩放竖屏UI [当手机横屏转竖屏时,对UI进行缩放]&)这个选项被用于调整你的UI的尺寸当屏幕处于竖屏模式,这类似于height-based调整,但他也会考虑宽度!4、小贴士UIRoot一直通过 2/ScreenHeight来缩放他自己,ScreenHeight要么是实际屏幕高度(在pixelHeight模式下),要么是你指定的手动高度(在fixed size模式下),在这种情况下,这个摄像机绘制UI能维持在正交为1的尺寸!如果你不需要UIRoot的自动缩放功能,你可以完全摆脱这个组件!5、类文档:以上是本人翻译自NGUI官网:/forum/index.php?topic=6710.0 & & 仅供参考!-------------------------------------------------------华丽的分割线----------------------------------------------------------------------------因为本人是新手,所以对上面的翻译文档做了些小实验,如下:结构图:& 图A:&图B:图A是Panel的背景图,也就是整个游戏的背景图,设置的大小为960 x 640,和屏幕的分辨率一样(不一样的话,图片不会完全显示),而btn是一个按钮,他的背景图是图B,设置的大小为 100 x 50最终效果图如下,就是简简单单的一个背景和一个sprite按钮而已:A1、PixelPerfect模式实验(屏幕分辨率不变,只改变maximum&minimum height)1、minimum
height &= 当屏幕的分辨率高度 &= maximum height&& )&& 图A的尺寸: 不变&& 图B的尺寸: 不变& &显示正常!2、当屏幕的分辨率高度 & maximum height&& 屏幕尺寸: &&不变(为 960 x 640)&& 图A的尺寸:
变大&& 图B的尺寸:
变大& &显示不正常!可以看出图A只显示了一部分,图B也变大了,并且也只显示了一部分3、当屏幕的分辨率高度 & minimum height& &屏幕尺寸:不变(为 960 x 640)&& 图A的尺寸:
变小&& 图B的尺寸:
变小& &显示不正常!图A和图B都变小了,并且出现了严重的灰边!4、总结:模式下,&最好设置:屏幕分辨率.height &=maximum height &避免UI被裁剪或产生灰边A2、PixelPerfect模式实验(屏幕分辨率改变,maximum&minimum height不变)以上都是基于分辨率不变的情况下进行的讨论,现在来看下分辨率变的情况,主要是看分辨率变化的情况,因为设备不同,分辨率也不同,有了A1实验的基础,我们知道最好这样设置:minimum height &= 屏幕分辨率.height &=maximum height,同样设置分辨率为 ,图片尺寸都不变,分别为960
x 640 和 100 x 50!、960
x 640 的分辨率 -& 1024 x 768 的分辨率
显示如下:图A图B的尺寸不变,依旧是960 x 640和100 x 50,而整个屏幕显示的尺寸就是1024 x 768,之所以出现灰边,是因为960 x 640 & 1024 x 768,这当然会出现灰边了2、960
x 640 的分辨率 -& 的分辨率显示如下:图A和图B的尺寸不变,而这个屏幕显示的尺寸就是650 x 500,出现了图片被遮挡的原因是960 x 640 & 650 x 500,所以肯定会被遮住!3、总结无论分辨率怎么变,UI的大小永远不会变,而整个屏幕的尺寸就是你设置的分辨率的尺寸!也就印证了官方文档对pixelperfect的解释了,最大的好处就是保证UI纹理的清晰!但是出现了被裁剪和产生灰边的,这个问题在最后讨论!B1、Fixed Size模式(分辨率不变,只改变manual height)图A,图B的尺寸不变,分别为960 x 640和100 x 50,分辨率依旧为 960 x 6401、分辨率的height = Manual
Height正常显示2、height & Manual Height& :变小& 图B:变小& 屏幕尺寸:不变(为 960 x 640)&出现了灰边,屏幕尺寸不变,图片变小了,当然出现灰边了!3、分辨率的height &
Manual Height&&图A:变大& 图B:变大& 屏幕尺寸:不变(为 960 x 640)&出现遮住了图片的情况,屏幕尺寸不变,图片变大了,当然出现遮住图片的情况了!4、总结manual height的值最好设置为等于分辨率的height,这个和pixelperfect模式的第一个实验差不多,都是只要屏幕分辨率的.height&(minimum |
manualheight) UI就会变小,屏幕分辨率的.height&(maximum |
manualheight) UI就会变大B2、Fixed Size模式(分辨率改变,manual height不变)同样有了B1实验的基础,我们知道最好这样设置:manual height =&屏幕分辨率.height ,同样设置分辨率为&,图片尺寸都不变,分别为960 x 640&和&100 x 50!、960 x 640&的分辨率&-& 1024 x 768&的分辨率显示如下:图A图B的尺寸变大,而整个屏幕显示的尺寸就是1024 x 768,之所以出现裁剪,是因为图片尺寸放大了!2、960 x 640&的分辨率&-&&的分辨率显示如下:图A和图B的尺寸变小,而这个屏幕显示的尺寸就是650 x 500,出现了图片被裁剪的情况!3、总结可以看出UI都是等比例的放大或者缩小了,这正是和pixelperfect模式的区别所在,pixelperfect模式随着分辨率的改变UI尺寸是不会变的,而Fixed size模式随着分辨率的改变UI尺寸会相应比例的放大或者缩小的!以上两种模式的分辨率改变实验都出现了灰边或者被裁剪的情况,如果我们设置不当的话,那么我们编的游戏在不同的设备上将会显示出我们无法预料的结果!C、解决不同分辨率的解决方法这里以Fixed size 模式进行讨论,因为他更能适应不同分辨率的要求,可以按比例缩放,而pixelperfect模式为了保证UI的清晰度所以尺寸是不变的,当放到分辨率高的设备上时,UI将会显得非常小,这样感觉总不是那么完美,而fixed size模式却可以根据不同的分辨率进行不同比例的缩放!目前的分辨率大概有这么多,我们来看看不同分辨率之间的切换所产生的问题:如果游戏的分辨率为5:4,那么当把游戏放到分辨率为4:3的设备上时,因为unity是根据height进行缩放的,所以高的比例为3/4,那么相应的宽,就要变为(3/4)*5,即得到UI在分辨率为4:3设备上显示的宽度了,如果(3/4)*5 & 4 会出现灰边,反之会被裁剪!5:4 -& 4:3 & & (3/4)*5 = 3.75 & 4 灰边& & & & & &3:2 & & (2/4)*5=2.5 & 3 灰边& & & & & 16:10 &(10/4)*5=12.5 & 16 灰边& & & & & 16:9 & &(9/4)*5=11.25 & 16.9 灰边4:3 -& 5:4 & (4/3)*4 =5.3333&5 &裁剪& & & & & &3:2 & & (2/3)*4 =2.6666&3 灰边& & & & & &16:10 & (10/3)*4 =13.3333 & 16 灰边& & & & & &16:9 & &(9/3)*4 = 12 &16 灰边3:2 -& 5:4 & (4/2)*3 &=6 &5 裁剪& & & & & &4:3 & (3/2)*3 =4.5 &4 裁剪& & & & & &16:10 &(10/2)*3 =15 &16 灰边& & & & & &16:9 & (9/2)*3 &= 13.5 &16 灰边16:10 -& 5:4 & (4/10)*16 =6.4 &5 裁剪& & & & & & & &4:3 &(3/10)*16 &=4.8 & 4 裁剪& & & & & & & &3:2 &(2/10)*16 =3.2 & 3 裁剪& & & & & & & &16:9 &(9/10)*16 =14.4 &16 灰边16:9 -& 5:4 &(4/9)*16 =7.1 & 5 裁剪&& & & & & & &4:3 &(3/9)*16 =5.3 & 4 裁剪& & & & & & &3:2 &(2/9)*16 =3.5 &3 裁剪& & & & & & &16:10 &(10/9)*16 =16.6 & 16 裁剪由以上可知:我们最好不要把16:9和16:10这两个尺寸设置成我们当前游戏的分辨率,因为这两个分辨率会产生裁剪,并且裁剪的比例很大,而5:4和4:3这两个分辨率产生灰边的比例很大,所以也不要,最后我们应选择3:2这个分辨率比较合适!因为他产生的灰边和裁剪的比例非常小,所以我们最后选择他!此时:我们设置游戏的分辨率为,manual height的值为800,为什么这么设置,上面实验已经说过了,在3:2分辨率情况下,我们先看裁剪这一块,我们只要知道被裁剪的最终尺寸是多少,我们也就确定了我们游戏应当所在的编辑区域了,超过这个区域就会被裁剪,此时,我们应当把分辨率设为被裁剪的最大值的分辨率,也就是5:4,切换到5:4分辨率,此时我们就知道了我们游戏编辑的区域了,假如黑色区域ABC为分辨率为3:2时的显示的样子,红色区域B为分辨率为5:4时显示的样子,那么我们的UI只能放在红色区域部分,不然会被裁剪!我想大家这个道理都懂!这样也就确定了编辑区域!&下面我们来讨论灰边问题,当我们的分辨率从3:2切换到16:9,也就出现了灰边,假如红色区域B为分辨率为3:2时的样子,黑色区域ABC为分辨率为16:9时的样子,那么AC就是灰边区域,此时我们最好的解决办法,就是改变背景图的宽度(高度自适应)加宽,从而使得背景图遮住灰边区域,背景图的宽度最好是最大灰边时的宽度,那怎么计算呢,假如游戏的分辨率是:2),要切换到16:9的分辨率下,背景图宽度就可以设置为800/9*16 即可!如果你觉得自己的UI只能存在那一固定被裁剪的区域不好的话,那么你可以配合UIAnchor使用,这样就可以达到了你想要的效果了!以上是个人的总结,如有不当,希望大家多多批评指正!在网上找了很多资料,很多感觉都不对,如果大家有好的方法,请分享下!在此谢过啦!
作者的其他最新博客
评论 ( 个评论)
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&