-
【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的位置,可以把父物體設置成跟設備分辨率大小一樣,然后把子物體根據錨點來設置相對位置。