3D坐標(biāo)系是在做3D項(xiàng)目開(kāi)發(fā)中的基礎(chǔ)概念,一般來(lái)說(shuō)3D軟件或者開(kāi)發(fā)工具都是采用笛卡爾坐標(biāo)系來(lái)描述物體的坐標(biāo)信息啡氢。笛卡爾坐標(biāo)系分為左手坐標(biāo)系和右手坐標(biāo)系术裸,左手坐標(biāo)系是Y軸指向上方,X軸指向右方辨绊,Z軸指向前方匹表;左宣鄙,右手坐標(biāo)系的X、Y軸方向相同冻晤,而Z軸是相反的,如圖1.1:
在Unity中使用的是左手坐標(biāo)系设江,其中X軸代表水平方向攘轩,Y軸代表垂直方向,Z軸代表深度歼捏,Unity中游戲?qū)ο蟮淖鴺?biāo)信息是放在一對(duì)括號(hào)里面笨篷,依次按照X、Y率翅、Z軸的順序來(lái)寫的冕臭,例如(2,2,2)瓢棒。
在Unity項(xiàng)目開(kāi)發(fā)過(guò)程中經(jīng)常會(huì)用到不同的坐標(biāo)系來(lái)描述場(chǎng)景空間中的物體位置丘喻,下面就介紹幾種常用的坐標(biāo)系。
1泉粉、全局(世界)坐標(biāo)系
全局坐標(biāo)系是用于描述場(chǎng)景內(nèi)所有物體位置和方向的基準(zhǔn)嗡靡,也稱為世界坐標(biāo)系。在Unity場(chǎng)景中創(chuàng)建的的物體都是以全局坐標(biāo)中的坐標(biāo)原點(diǎn)(0,0,0)來(lái)確定各自的位置讨彼。如圖1.2,我們就創(chuàng)建一個(gè)Cube物體
在Inspector視圖的Transform組件中可以觀察到Cube的坐標(biāo)信息哩至,此時(shí)的Position屬性是(0,0,0)就表示了該物體的全局坐標(biāo)蜜自。我們通常在代碼中用transform.position來(lái)獲取全局坐標(biāo)。
2箭阶、局部坐標(biāo)
Unity場(chǎng)景中戈鲁,每一個(gè)物體都有自己獨(dú)立的坐標(biāo)系,并且會(huì)隨著物體的旋轉(zhuǎn)或者移動(dòng)而改變诈乒,也稱為模型坐標(biāo)系或物體坐標(biāo)系鸣皂;模型mesh保存的頂點(diǎn)均為局部坐標(biāo)系下的坐標(biāo)。Transform組件中Position表示的其實(shí)也是局部坐標(biāo)寞缝,圖1.2中之所以表示的是世界坐標(biāo),是因?yàn)樾聞?chuàng)建的Cube并沒(méi)有父級(jí)滩届,此時(shí)Cube自己就相當(dāng)于自己的父級(jí)被啼,所以它的Position表示的既是自己的局部坐標(biāo)也是世界坐標(biāo)棠枉。在工具欄中單擊Global按鈕可以切換現(xiàn)實(shí)全局坐標(biāo)系和局部坐標(biāo)系泡挺,如圖1.3就是局部坐標(biāo)系
在Unity中娄猫,可以在Hierarchy視圖中將一個(gè)游戲?qū)ο笸系搅硪粋€(gè)對(duì)象上來(lái)建立父子關(guān)系,這樣就使得被拖動(dòng)的物體成為了另一個(gè)物體的子物體媳溺,父子物體的坐標(biāo)系是關(guān)聯(lián)的,此時(shí)子物體會(huì)以父物體的局部坐標(biāo)點(diǎn)為自身的坐標(biāo)原點(diǎn)扯躺,此時(shí)子物體的Position屬性值顯示的就是該物體相對(duì)于父物體的局部坐標(biāo)蝎困。如圖1.4表示了新建的Sphere物體,將以該物體為父物體:
然后我們就把Cube拖到Sphere下钦无,后觀察Cube的Transform組件的變化盖袭。如圖1.5:
可以看出Cube的Position值變成了在相對(duì)于其父物體Sphere局部坐標(biāo)系時(shí)的位置鳄虱。在代碼中我們可以用transform.localposition來(lái)獲取局部坐標(biāo)凭峡。
3、相機(jī)坐標(biāo)系
根據(jù)觀察位置和方向建立的坐標(biāo)系摧冀。使用此坐標(biāo)系可以方便地判斷物體是否在相機(jī)前方以及物體之間的先后遮擋順序等。
4建车、屏幕坐標(biāo)系
屏幕坐標(biāo)系是一個(gè)三維坐標(biāo)系椒惨,Z軸是以相機(jī)的世界單位來(lái)衡量的。該坐標(biāo)系通常用來(lái)描述像素在屏幕上的位置领斥,它的范圍是以左下角為(0,0),右上角為(Screen.width,Screen.height)定義的這樣一個(gè)矩形月洛,就是屏幕的大小。也就是我們的Game視圖导而。
屏幕坐標(biāo)和相機(jī)之間的關(guān)系:Screen.width=Camera.pixelWidth和Screen.height=Camera.pixelHeight這兩個(gè)條件隔崎。例如我們將相機(jī)正對(duì)著場(chǎng)景中的原點(diǎn)(0,0,0),相機(jī)的Z軸分量為-10,按照屏幕坐標(biāo)的定義虚缎,假設(shè)屏幕為800X640的大小钓株,則此時(shí)原點(diǎn)轉(zhuǎn)化為屏幕坐標(biāo)后應(yīng)該是(400,320,10)。下面我們就做一個(gè)屏幕坐標(biāo)的實(shí)驗(yàn)轴合。
我們先創(chuàng)建一個(gè)腳本,寫好代碼讓它可以打印出我們鼠標(biāo)點(diǎn)擊Game視圖時(shí)點(diǎn)擊位置的屏幕坐標(biāo)题涨。
腳本代碼:
<code>
void Start () {
}
void Update () {
if (Input.GetMouseButtonDown(0))//判斷是否按下鼠標(biāo)左鍵
{
Vector3 vec = Input.mousePosition;//設(shè)一個(gè)三維向量用來(lái)存放鼠標(biāo)點(diǎn)擊時(shí)的坐標(biāo)总滩,此時(shí)Z軸為0
vec.z = this.transform.position.z;//把Z的坐標(biāo)換做相機(jī)的Z軸坐標(biāo),因?yàn)槟_本在相機(jī)上席函,所以用this點(diǎn)出
print(vec);//打印出鼠標(biāo)按下時(shí)的屏幕坐標(biāo)
}
}
</code>
我們把這個(gè)腳本放到相機(jī)上面冈涧,然后調(diào)整一下Game視圖的大小,如圖1.6:
最后運(yùn)行項(xiàng)目营曼,在Game視圖中點(diǎn)擊鼠標(biāo)左鍵咽筋,我們分別點(diǎn)擊Game視圖的左下角、右下角蒜危、左上角和右上角,觀察Console視圖的打印內(nèi)容部翘,如圖1.7:
有圖我們得以驗(yàn)證:左下角就是屏幕坐標(biāo)系的原點(diǎn)响委,水平方向就是X軸,垂直方向就是Y軸夹囚,Z軸就是相機(jī)的Z軸坐標(biāo)-4邀窃。
5、視口坐標(biāo)系
視口坐標(biāo)是標(biāo)準(zhǔn)化后的屏幕坐標(biāo)瞬捕。標(biāo)準(zhǔn)化的概念我們可以引申到向量的標(biāo)準(zhǔn)化中,比如一個(gè)向量(x,y)將過(guò)標(biāo)準(zhǔn)化后可以得到一個(gè)單位向量(x’,y’)劣砍。類似地扇救,視口坐標(biāo)是以0到1間的數(shù)字來(lái)表示的,它的范圍是以左下角為(0,0),右上角為(1,1)定義的這樣一個(gè)矩形仅讽。視口坐標(biāo)是一個(gè)3D坐標(biāo)钾挟,Z軸是以相機(jī)的世界單位來(lái)衡量的饱岸。
通過(guò)對(duì)比可以發(fā)現(xiàn)視口坐標(biāo)和屏幕坐標(biāo)特別的相似,所以這里大家可以對(duì)比著來(lái)學(xué)習(xí)汤锨。同樣以屏幕坐標(biāo)中的例子來(lái)將這里的轉(zhuǎn)換百框,例如我們將相機(jī)正對(duì)著場(chǎng)景中的原點(diǎn)(0,0,0),相機(jī)的Z軸分量為-10,按照屏幕坐標(biāo)的定義,假設(shè)屏幕為800X640的大小慎菲,則此時(shí)原點(diǎn)轉(zhuǎn)化為屏幕坐標(biāo)后應(yīng)該是(0.5,0.5,10)锨并。
介紹好坐標(biāo)系,我們下面介紹一下幾種常用的坐標(biāo)系之間的轉(zhuǎn)換方法
1解幼、屏幕坐標(biāo)轉(zhuǎn)世界坐標(biāo)
在Unity3D中通過(guò)camera.ScreenToWorldPoint(Vector3 v)方法可以將一個(gè)屏幕坐標(biāo)轉(zhuǎn)化為世界坐標(biāo)包警。其中,camera是游戲場(chǎng)景中的場(chǎng)景相機(jī)(不一定非要是主相機(jī))害晦。通過(guò)Input.mousePosition或者 Input.touches[0].position可以獲得鼠標(biāo)或者單根手指的屏幕坐標(biāo)篱瞎。
2、世界坐標(biāo)轉(zhuǎn)屏幕坐標(biāo)
在Unity3D中通過(guò)camera.WorldToScreenPoint(Vector3 v)方法可以將一個(gè)世界坐標(biāo)轉(zhuǎn)化為屏幕坐標(biāo)俐筋。其中澄者,camera是游戲場(chǎng)景中的UI相機(jī)。比如我們需要將一個(gè)世界坐標(biāo)轉(zhuǎn)換到NGUI坐標(biāo)的時(shí)候粱挡,可以使用場(chǎng)景相機(jī)將世界坐標(biāo)轉(zhuǎn)為屏幕坐標(biāo),然后再利用UI相機(jī)將屏幕坐標(biāo)轉(zhuǎn)換為世界坐標(biāo)询筏,最后再賦值給NGUI控件榕堰。
3、屏幕坐標(biāo)轉(zhuǎn)視口坐標(biāo)
在Unity3D中可以通過(guò)camera.ScreenToViewportPoint()來(lái)將一個(gè)屏幕坐標(biāo)轉(zhuǎn)換為視口坐標(biāo)嫌套,其中camera是游戲場(chǎng)景中的場(chǎng)景相機(jī)逆屡。
4、世界坐標(biāo)轉(zhuǎn)視口坐標(biāo)
在Unity3D中可以通過(guò)camera.WorldToViewportPoint()來(lái)將一個(gè)世界坐標(biāo)轉(zhuǎn)換為視口坐標(biāo)踱讨,其中camera是游戲場(chǎng)景中的場(chǎng)景相機(jī)魏蔗。