系列传送门
IOS:
IOS:使用shell命令打包并上传Itunes
Unity3d:
Unity3d:Canvas适配屏幕分辨率与锚点(Anchors与Pivot)
Unity3d:在屏幕边缘显示其他玩家方位
Unity3d:命令行打包Android
Unity3d:命令行编译IOS
Unity3d:使用Jenkins自动编译打包IOS(只能打包Development)
Unity3d:使用Jenkins自动编译打包IOS(打包Ad-hoc,上传itunes)
提前预知:文章中Width和Height等属性的使用是伪代码,理解意思就好。
1、Root Canvas(适配屏幕分辨率)
所有的UI都有一个Root Canvas,该Canvas的RectTransform不可修改。
所有Canvas坐标系方向都是右侧为X轴正方向,上方为Y轴正方向。
该Canvas还带有一个Canvas Scaler组件,可以通过该组件适配不同的屏幕分辨率。
必须注意:Canvas的宽高和屏幕分辨率不是一回事。
UI Scale Mode
Canvas Scaler中有一个UI Scale Mode属性,用于确定画布中的UI元素如何缩放。
以下假如屏幕分辨率为1500 * 3000。
1.1、Constant Pixel Size
使Canvas宽高保持与屏幕分辨率一致。屏幕分辨率有多大,Canvas宽高就有多大( Scale Factor缩放因子为1时)。
-
Scale Factor
按此因子缩放画布中的所有UI元素。
默认缩放因子为1,则此时Canvas宽高也为1500 * 3000。
如果缩放因子为2,则Canvas宽高为屏幕分辨率/2,即750 * 1500,也就是说Canvas上的UI是原来的2倍大小。
所以,Canvas宽高 = 屏幕分辨率 / 缩放因子。
1.2、Scale With Screen Size
使Canvas的宽高比与屏幕分辨率的宽高比保持一致。
缩放时需要基于下面的Reference Resolution(参考分辨率)进行缩放。
因为此时屏幕分辨率的宽高比为:1500 / 3000 = 0.5,所以在该模式下,无论怎么调整参数,Canvas宽高比也一直为0.5,不会变。
所以,Canvas宽高比 = 屏幕分辨率宽高比。
1.2.1、Reference Resolution
缩放时用的参考分辨率。
下面假设参考分辨率是1080 * 1920。
1.2.2、Screen Match Mode
如果屏幕分辨率与参考分辨率的宽高比不一致,则根据选择的模式对Canvas宽高进行缩放。
如果屏幕分辨率与参考分辨率的宽高比一致,该选项怎么调都不管用。
1.2.2.1、Match Width or Height
基于下面Match对Canvas宽高进行缩放。
-
Match
取值范围(0~1)的浮点数。
是一个缩放参考值,用于确定对参考分辨率的宽进行缩放,还是对参考分辨率的高进行缩放。
越靠近左边的Width,则更倾向于对参考分辨率的高进行缩放。
越靠近右边的Height,则更倾向于对参考分辨率的宽进行缩放。
拖动Slider或设置值之后,Unity会自动计算对应的Canvas宽高。把Slider拖动到Width最左边,即Match=0。此时只对Canvas高进行缩放,Canvas的宽与参考分辨率的宽保持一致,都是1080。因为Canvas宽高比为0.5,所以此时Canvas高为1080 / 0.5 = 2160。
把Slider拖动到Height最右边,即Match=1。此时只对Canvas宽进行缩放,Canvas的高与参考分辨率的高保持一致,都是1920。因为Canvas宽高比为0.5,所以此时Canvas宽为1920 * 0.5 = 960。
把Slider拖动到介于Width与Height中间的一个位置,比如Match=0.2,更靠近左边的Width,此时会更倾向于对参考分辨率的高进行缩放。
1.2.2.2、Expand
缩放后,Canvas的宽高一定不低于参考分辨率的宽高。
假如使用参考分辨率的宽进行缩放,即保持Canvas的高等于参考分辨率的高。因为Canvas宽高比为0.5,所以此时Canvas的宽为1920 * 0.5 = 960,低于参考分辨率的宽,不符合Expand模式的缩放要求。
假如使用参考分辨率的高进行缩放,即保持Canvas的宽等于参考分辨率的宽。因为Canvas宽高比为0.5,所以此时Canvas的高为1080 / 0.5 = 2160,高于(不低于)参考分辨率的高,完全符合Expand模式的缩放要求。
该模式下,最终Canvas的宽高分别是1080,2160。
1.2.2.3、Shrink
缩放后,Canvas的宽高一定不高于参考分辨率的宽高。与Expand类似。
- 该模式下,最终Canvas的宽高分别是960,1920。
2、UI的锚点(Anchors与Pivot)
锚点说难不难,只是不好描述,但可以用例子来说明。
假如Canvas拥有一个Image节点。
对于Image所在的坐标系,坐标系方向与Canvas坐标系方向相同。
下面看下Image节点的锚点在Canvas的不同位置的情况:
left | center | right | stretch | |
---|---|---|---|---|
top |
左上角 单锚点 Anchors.Min(0, 1) Anchors.Max(0, 1) |
顶部边框的中心 单锚点 Anchors.Min(0.5, 1) Anchors.Max(0.5, 1) |
右上角 单锚点 Anchors.Min(1, 1) Anchors.Max(1, 1) |
左上角、右上角 双锚点 Anchors.Min(0, 1) Anchors.Max(1, 1) |
middle |
左侧边框的中心 单锚点 Anchors.Min(0, 0.5) Anchors.Max(0, 0.5) |
正中心 单锚点 Anchors.Min(0.5, 0.5) Anchors.Max(0.5, 0.5) |
右侧边框的中心 单锚点 Anchors.Min(1, 0.5) Anchors.Max(1, 0.5) |
左侧边框的中心、右侧边框的中心 双锚点 Anchors.Min(0, 0.5) Anchors.Max(1, 0.5) |
bottom |
左下角 单锚点 Anchors.Min(0, 0) Anchors.Max(0, 0) |
底部边框的中心 单锚点 Anchors.Min(0.5, 0) Anchors.Max(0.5, 0) |
右下角 单锚点 Anchors.Min(1, 0) Anchors.Max(1, 0) |
左下角、右下角 双锚点 Anchors.Min(0, 0) Anchors.Max(1, 0) |
stretch |
左上角、左下角 双锚点 Anchors.Min(0, 0) Anchors.Max(0, 1) |
底部边框的中心、顶部边框的中心 双锚点 Anchors.Min(0.5, 0) Anchors.Max(0.5, 1) |
右上角、右下角 双锚点 Anchors.Min(1, 0) Anchors.Max(1, 1) |
左下角、左下角、右上角、右下角 四锚点 Anchors.Min(0, 0) Anchors.Max(1, 1) |
2.1、单锚点
单锚点,从Unity上看,就是4个小三角形聚在一个点。
单锚点在Canvas的位置(假设为点p)都满足以下逻辑:
注意:锚点不一定是Image所在坐标系的原点。
-
锚点的Pivot(0, 0)
Image所在坐标系原点在Canvas中的坐标为(p.x + Image.Width/2, p.y + Image.Height/2)。 -
锚点的Pivot(0, 0.5)
Image所在坐标系原点在Canvas中的坐标为(p.x + Image.Width/2, p.y)。 -
锚点的Pivot(0, 1)
Image所在坐标系原点在Canvas中的坐标为(p.x + Image.Width/2, p.y - Image.Height/2)。 -
锚点的Pivot(0.5, 0)
Image所在坐标系原点在Canvas中的坐标为(p.x, p.y + Image.Height/2)。 -
锚点的Pivot(0.5, 0.5)
Image所在坐标系原点在Canvas中的坐标为(p.x, p.y),此时锚点即Image所在坐标系的原点。 -
锚点的Pivot(0.5, 1)
Image所在坐标系原点在Canvas中的坐标为(p.x, p.y - Image.Height/2)。 -
锚点的Pivot(1, 0)
Image所在坐标系原点在Canvas中的坐标为(p.x - Image.Width/2, p.y + Image.Height/2)。 -
锚点的Pivot(1, 0.5)
Image所在坐标系原点在Canvas中的坐标为(p.x - Image.Width/2, p.y)。 -
锚点的Pivot(1, 1)å
Image所在坐标系原点在Canvas中的坐标为(p.x - Image.Width/2, p.y - Image.Height/2)。
可以总结出以下公式(p为单锚点在Canvas的位置,pivot为单锚点的Pivot属性):
Image所在坐标系原点在Canvas中的坐标 = (p.x + Image.Width * (0.5 - pivot.x), p.y + Image.Height * (0.5 - pivot.y))。
2.2、双锚点
双锚点,从Unity上看,就是2个小三角形聚在一个点。
2.2.1、左上角、左下角
左上角有2个小三角形,左下角有2个小三角形
此时,Image拥有PosX,Top,Width,Bottom这四个位置参数。
而且,锚点的Pivot的Y不起作用。
Image的Height = (Canvas.Height - Top - Bottom) / 2。
如果设置Image的Top,Bottom都为0的话,则Image的高会与Canvas的高一致。
Image所在坐标系原点在Canvas中的坐标 = (Image.Width * (0.5 - Pivot.x) + PosX , Image.Height / 2 + Top)。
2.2.2、底部边框的中心、顶部边框的中心
底部边框的中心有2个小三角形,顶部边框的中心有2个小三角形
此时,Image拥有PosX,Top,Width,Bottom这四个位置参数。
而且,锚点的Pivot的Y不起作用。
Image的Height = (Canvas.Height - Top - Bottom) / 2。
如果设置Image的Top,Bottom都为0的话,则Image的高会与Canvas的高一致。
Image所在坐标系原点在Canvas中的坐标 = (Image.Width * (0.5 - Pivot.x) + Canvas.Width / 2 + PosX , Image.Height / 2 + Top)。
2.2.3、右上角、右下角
右上角有2个小三角形,右下角有2个小三角形
此时,Image拥有PosX,Top,Width,Bottom这四个位置参数。
而且,锚点的Pivot的Y不起作用。
Image的Height = (Canvas.Height - Top - Bottom) / 2。
如果设置Image的Top,Bottom都为0的话,则Image的高会与Canvas的高一致。
Image所在坐标系原点在Canvas中的坐标 = (Image.Width * (0.5 - Pivot.x) + Canvas.Width + PosX , Image.Height / 2 + Top)。
2.2.4、左上角、右上角
左上角有2个小三角形,右上角有2个小三角形
此时,Image拥有Left,PosY,Right,Height这四个位置参数。
而且,锚点的Pivot的X不起作用。
Image的Width = (Canvas.Width - Left - Right) / 2。
如果设置Image的Left,Right都为0的话,则Image的宽会与Canvas的宽一致。
Image所在坐标系原点在Canvas中的坐标 = (Image.Width / 2 + Left , Image.Height * (0.5 - Pivot.x) + PosY)。
2.2.5、左侧边框的中心、右侧边框的中心
左侧边框的中心有2个小三角形,右侧边框的中心有2个小三角形
此时,Image拥有Left,PosY,Right,Height这四个位置参数。
而且,锚点的Pivot的X不起作用。
Image的Width = (Canvas.Width - Left - Right) / 2。
如果设置Image的Left,Right都为0的话,则Image的宽会与Canvas的宽一致。
Image所在坐标系原点在Canvas中的坐标 = (Image.Width / 2 + Left , Image.Height * (0.5 - Pivot.x) + Canvas.Height / 2 + PosY)。
2.2.6、左下角、右下角
左下角有2个小三角形,右下角有2个小三角形
此时,Image拥有Left,PosY,Right,Height这四个位置参数。
而且,锚点的Pivot的X不起作用。
Image的Width = (Canvas.Width - Left - Right) / 2。
如果设置Image的Left,Right都为0的话,则Image的宽会与Canvas的宽一致。
Image所在坐标系原点在Canvas中的坐标 = (Image.Width / 2 + Left , Image.Height * (0.5 - Pivot.x) + Canvas.Height + PosY)。
2.3、四锚点(左下角、左下角、右上角、右下角)
四锚点,从Unity上看,就是4个小三角形全都是分散的(左下角、左下角、右上角、右下角)。
此时,Image拥有Left,Top,Right,Bottom这四个位置参数。
而且,锚点的Pivot不起作用。
Image的Width = (Canvas.Width - Left - Right) / 2。
Image的Height = (Canvas.Height - Top - Bottom) / 2。
如果设置Image的Left,Top,Right,Bottom都为0的话,则Image的宽高会与Canvas的宽高一致。
Image所在坐标系原点在Canvas中的坐标 = (Image.Width / 2 + Left , Image.Height / 2 + Top)。
3、屏幕坐标与Canvas坐标相互转换
3.1、屏幕坐标系与Canvas坐标系
屏幕坐标系与Canvas坐标系都是左下角为原点,向右为X轴正方向,向上为Y轴正方向。
3.2、屏幕坐标转换到Canvas坐标系上
在屏幕坐标系上有个点P(x, y),我们先把屏幕分辨率的宽高缩放到与Canvas的宽高一致,此时P点的坐标也会随着缩放。
因为屏幕坐标系与Canvas坐标系都是左下角为原点,所以缩放完成后的P的位置(记作P2),就是P点在Canvas坐标系上的位置。
P2 = (P.x * Canvas.Width / Screen.Width, P.y * Canvas.Height / Screen.Height)
现在有一个Image UI,我们先把该Image的锚点设置为左下角(Anchors.Min(0, 0),Anchors.Max(0, 0)),然后把P2的位置赋值给Image的anchoredPosition,此时该Image刚好就在P点的位置。
3.3、Canvas坐标转换到屏幕坐标系上
在Canvas坐标系上有一个Image UI,我们先把该Image的锚点设置为左下角(Anchors.Min(0, 0),Anchors.Max(0, 0)),然后把Canvas的宽高缩放到与屏幕分辨率的宽高一致,此时Image的anchoredPosition(记作P)也会随着缩放。
因为屏幕坐标系与Canvas坐标系都是左下角为原点,所以缩放完成后的Image的anchoredPosition(记作P2),就是Image在屏幕坐标系上的位置。
P2 = (P.x * Screen.Width / Canvas.Width, P.y * Screen.Height / Canvas.Height)