自适应讲解部分可以参考以下网址:http://www.xuanyusong.com/archives/2536,下面代码中提到的AdaptiveManualHeight()函数就是参考该文章的。
下面主要说的就是背景图、全屏透明Sprite和控件位置自适应的东西。
由于我们所要开发的游戏只支持800x480及以上的分辨率的手机,因此分辨率小于800x480的自适应这里不考虑(其实都差不多的,就是多了一个if判断,然后分别调整下背景图、全屏透明背景而已)
见下图,背景图和全屏sprite(这里为了方便观看,背景图和全屏sprite就没重叠,且全屏sprite设置成透明灰色而不是完全透明)不是父子关系,处于九宫格位置的控件可以使用Anchors来固定在屏幕中的相对位置,UIRoot的Scaling Style属性选择FixedSizeOnMobiles(PS:这个属性要再IOS或者Android平台上才能起作用,为什么可以看UIRoot里面的代码有条件编译,我是在BlueStacks安卓模拟器上运行此测试案例的),ManualHeight就是你实际设计UI时定的高度(可参照上面网址中雨凇momo所讲解的)
首先确定设计时用的宽高为designWidth、designHeight;实际屏幕宽高为realScreenWidth、realScreenHeight;
widthScale = realScreenWidth/designWidth;
heightScale = realScreenHeight/designHeight;
1.因为实际游戏中,背景图一般都是带有不规则图案的(如果宽高不是等比缩放的话,则图案就会变形),因此背景图按照widthScale 与heightScale之间的大者进行缩放(比如设计时定下的屏幕宽高为800x480,实际手机分辨率960x640,那960/800=1.2, 640/480=1.333,那么此时取1.333为背景图的缩放值),这样的话背景图就能铺满整个屏幕不会出现黑边且不变形,但是一般会超出屏幕,这个时候可以让背景图居中(当然了,需要让美术在设计的时候将背景图的重点图案放在中间,边角位置不要放重点图案,这样的话背景图的边缘位置就不会有什么重要信息,也就是发生裁切了也没什么关系)
2.由于游戏中处于九宫格位置的(比如左上角、左下角、右上角、右下角、还有中间、左中间等等其他的区域)控件需要贴着屏幕边缘,这个时候就是要用锚点Anchors(其Target在本例中是指FullScreenSprite)来自动调整,而此时完全透明的Sprite(UIRoot中的ManualHeight缩放起作用之后,将Sprite拉伸至整个屏幕)就起了这个作用,除了背景图外的所有控件都是全透明Sprite的子控件。这样UIRoot缩放起作用之后处于九宫格位置的控件也可以贴边!
具体的见以下代码吧:
1 using UnityEngine; 2 using System.Collections; 3 using System; 4 5 public class Test : MonoBehaviour 6 { 7 public UIRoot mUIRoot = null; 8 public UISprite mBackgroundSprite = null; 9 public UISprite mFullScreenSprite = null; 10 11 private const int cDesignWidth = 800; 12 private const int cDesignHeight = 480; 13 private int mRealScreenWidth = 0; 14 private int mRealScreenHeight = 0; 15 16 private readonly float mWidthScale = Convert.ToSingle(Screen.width) / cDesignWidth; 17 private readonly float mHeightScale = Convert.ToSingle(Screen.height) / cDesignHeight; 18 19 void Awake() 20 { 21 CalculateScreenWidthHeight(); 22 } 23 24 void Start() 25 { 26 Assert.IsNotNull(mUIRoot, "Test.Start(), mUIRoot is null"); 27 Assert.IsNotNull(mBackgroundSprite, "Test.Start(), mBackgroundSprite is null"); 28 Assert.IsNotNull(mFullScreenSprite, "Test.Start(), mFullScreenSprite is null"); 29 30 AdaptiveManualHeight(mUIRoot); 31 AdaptiveBackgroundSprite(mBackgroundSprite); 32 AdaptiveFullScreenSprite(mFullScreenSprite); 33 } 34 35 private void CalculateScreenWidthHeight() 36 { 37 float scale = (float)mUIRoot.activeHeight / Screen.height; 38 mRealScreenWidth = Mathf.CeilToInt(Screen.width * scale); 39 mRealScreenHeight = Mathf.CeilToInt(Screen.height * scale); 40 } 41 42 public void AdaptiveManualHeight(UIRoot uiRoot) 43 { 44 Assert.IsNotNull(uiRoot, "Test.AdaptiveManualHeight(), uiRoot is null"); 45 if (Convert.ToSingle(Screen.height) / Screen.width > Convert.ToSingle(cDesignHeight) / cDesignWidth) 46 { 47 uiRoot.manualHeight = Mathf.RoundToInt(Convert.ToSingle(cDesignWidth) / Screen.width * Screen.height); 48 } 49 else 50 { 51 uiRoot.manualHeight = cDesignHeight; 52 } 53 } 54 55 //自适应背景图,按宽宽比、高高比的大者缩放 56 public void AdaptiveBackgroundSprite(UISprite backgroundSprite) 57 { 58 //此if语句针对屏幕宽或高大于设计时所定的宽或高 59 if (mRealScreenWidth > backgroundSprite.width || mRealScreenHeight > backgroundSprite.height) 60 { 61 int adaptiveHeight = Mathf.RoundToInt(cDesignHeight * mHeightScale); 62 int adaptiveWidth = Mathf.RoundToInt(cDesignWidth * mHeightScale); 63 if (mHeightScale <= mWidthScale) 64 { 65 adaptiveHeight = Mathf.RoundToInt(cDesignHeight * mWidthScale); 66 adaptiveWidth = Mathf.RoundToInt(cDesignWidth * mWidthScale); 67 } 68 backgroundSprite.SetDimensions(adaptiveWidth, adaptiveHeight); 69 } 70 } 71 72 public void AdaptiveFullScreenSprite(UISprite fullScreenSprite) 73 { 74 fullScreenSprite.SetDimensions(mRealScreenWidth, mRealScreenHeight); 75 } 76 }
上面代码我在很多分辨率下都测试过(当然要是大于等于800x480的分辨率),如果要支持800x480以下分辨率的,那么自己修改函数
AdaptiveBackgroundSprite(),就是加个else语句做多个调整。
如果存在什么问题或者更好的建议麻烦告知,不胜感激!