Unity3D屏幕自适应
-
【Unity3D的四种坐标系】
- World Space(世界坐标):我们在场景中添加物体(如:Cube),他们都是以世界坐标显示在场景中的。transform.position可以获得该位置坐标。
- Screen Space(屏幕坐标):以像素来定义的,以屏幕的左下角为(0,0)点,右上角为(Screen.width,Screen.height),Z的位置是以相机的世界单位来衡量的。注:鼠标位置坐标属于屏幕坐标,Input.mousePosition可以获得该位置坐标,手指触摸屏幕也为屏幕坐标,Input.GetTouch(0).position可以获得单个手指触摸屏幕坐标。Screen.width = Camera.pixelWidth ,Screen.height = Camera.pixelHeigth
- ViewPort Space(视口坐标):视口坐标是标准的和相对于相机的。相机的左下角为(0,0)点,右上角为(1,1)点,Z的位置是以相机的世界单位来衡量的。
- GUI界面的坐标系:这个坐标系与屏幕坐标系相似,不同的是该坐标系以屏幕的左上角为(0,0)点,右下角为(Screen.width,Screen.height)。
注意:实际屏幕坐标也是三维的,后面三种坐标的Z轴都是相对与摄像机的距离。
-
【四种坐标系的转换】
- 世界坐标→屏幕坐标:camera.WorldToScreenPoint(transform.position);这样可以将世界坐标转换为屏幕坐标。其中camera为场景中的camera对象。
- 屏幕坐标→视口坐标:camera.ScreenToViewportPoint(Input.GetTouch(0).position);这样可以将屏幕坐标转换为视口坐标。其中camera为场景中的camera对象。
- 视口坐标→屏幕坐标:camera.ViewportToScreenPoint();
- 视口坐标→世界坐标:camera.ViewportToWorldPoint()
- 【坐标系中的变换】
- 平移,旋转,缩放。
- 旋转和缩放发生在局部坐标系上,以局部坐标原点为中心点,两者还满足交换率。
- 平移发生在父坐标系上。
所以实现时,会先算好旋转和缩放,再算平移。Unity的转动顺序是YXZ,中间的轴是X。因为围绕Y轴的水平摇摆最常见,围绕X轴的垂直俯仰次常用,而围绕Z轴的歪脑袋最少用。
-
【Canvas 设置】
- Canvas.RenderMode:ScreenSpace - Overlay
Canvas作为2D图像,永远处于屏幕的最前方,即使没有相机也能够看到内容。如果画布发生大小改变,也能够自动改变尺寸来匹配屏幕。
- 当ScreenOverlay的情况,因为根本没有经过投影空间,而是直接在屏幕空间绘制,因为在屏幕空间的坐标直接绘制像素,所以Canvas的RectTransform的width*scaleX必须等于屏幕的宽、RectTransform的height*scaleY必须等于屏幕的高。
- Overlay情况下,Scene View是世界空间的、Canvas是屏幕空间的,两者处于不同空间,它们的大小比较也就没有可比性了,Unity这里的Editor实现是,屏幕空间1像素等于世界空间1米地把Canvas在SceneView显示出来
Canvas的核心功能是,自动根据屏幕设备的分辨率、当前的scaleXY,算出正确的width和height,确保和屏幕匹配。
Canvas.RectTransform.scaleXYZ = Canvas.scaleFactor
scaleFactor = Mathf.Min(screenSize.x / m_ReferenceResolution.x, screenSize.y / m_ReferenceResolution.y);
scaleFactor尽可能小,结果是尽量把UI在设备屏幕给放大
1024/1280=0.8 < 720/768 所以缩放是0.8,然后将设备分辨率根据除0.8来得到适合的1280*960大小。
设备分辨率1024*768时,基准分辩率是1280*720,unity会根据1024和768来进行缩放Canvas的width、height、scale,根据宽固定,缩放高度,即把1280缩小到1024是0.8倍,然后根据720/0.8得到960,大小缩放Scale是0.8,自动调整大小为1280*960。
- Canvas.RenderMode:ScreenSpace - Camera
可以指定摄像机,和Screen Space-Overlay类似,但是有物体比Canvas更加接近摄像机时会显示在前面,反之则会被Canvas遮挡。
- 由于使用了Camera,所以此时的Canvas和Scene View里的任意GameObject一样,都是处于世界空间了。
- 所以对于ScreenSpace - Camera的Canvas来说,关键是如何把处于世界空间中的Canvas能够占满投影空间的投影平面。
- 所以在Camera模式下,相当要把世界坐标的Canvas转化为屏幕坐标,要根据2D相机和Canvas的plane distance,Size
- Canvas.RectTransform.scaleXYZ = Canvas.scaleFactor * scaleFactorCamera
-
正交(Orthographic)Camera 2D模式下,Size的定义为视体的投影平面高的1/2。 比如Camera的Size是3.6,即投影平面高为500
设备分辨率1024*768时,因为世界空间转化到屏幕空间,所以Plane Distance相当于移动z轴相反的500,到原点。
size = 3.6米=360像素,所以相机的高度=2*size = 720像素,根据基准分辩率宽就是1280。所以基准分辩率是1280*720,
- Canvas.height==Screen.height = 768
- Canvas.height * scaleFactor * scaleFactorCamera = Camera.size * 2
- 768 * scaleFactor * scaleFactorCamera = 3.6 * 2
- 所以scaleFactorCamera = Camera.size * 2 / Canvas.height / scaleFactor = Camera.size * 2 / Screen.height / scaleFactor
- Canvas.RenderMode:World Space:可以指定摄像机,把Canvas视为一个3D物体来处理,可以设置位置和大小。
- 【Screen Match Mode—Expand】
当屏幕分辨率大于参考分辨率时,选择变化较小的一个方向(横向还是纵向),作为放大Canvas Scale的标准,另一方向上的变化则是在整体缩放以后再进行补偿性的变化。此举旨在减少扩大分辨率时由于非等比扩大而对UI整体布局造成影响。适合制作较小标准尺寸,扩充到较大屏幕。
- 【锚点】
AnchorsMin:锚框左下角的点
AnchorsMax:锚框右上角的点
当AnchorsMin和AnchorsMax不在同一水平线或垂直线上的时候,就形成了锚框;
当AnchorsMin和AnchorsMax两个点重合的时候,就形成了一种特殊情况:锚点
注册点(Pivot):注册点就是自身的中心点,也是个归一化的点
当使用的是锚点的时候,使用的是绝对位置,被子物体定上锚点的父物体的大小改变、移动都不会改变子物体锁定的锚点到子物体注册点(Pivot)之间的距离。
-
总结:
Render Mode 选择为Camera
UI Scale Mode选择screen Size
Match Mode选择Expand
UI内的子物体通过设置锚点固定在UI的位置,可以把父物体设置成跟设备分辨率大小一样,然后把子物体根据锚点来设置相对位置。