翻譯-在Unity3D中的旋轉(zhuǎn)和方向

概述

在3D軟件中旋轉(zhuǎn)通常用四元數(shù)或者歐拉角來(lái)表示,各有優(yōu)缺點(diǎn)。Unity內(nèi)部存儲(chǔ)使用四元數(shù),但是為了方便我們編輯,在面板上顯示成對(duì)應(yīng)的歐拉角的值。

Euler Angles 歐拉角

歐拉角簡(jiǎn)單的理解就是有三個(gè)角度X,Y,Z,然后按順序在對(duì)應(yīng)的軸上進(jìn)行旋轉(zhuǎn),最后物體的方向就是這個(gè)歐拉角。

  • 優(yōu)點(diǎn):容易直觀的理解值的意義
  • 缺點(diǎn):會(huì)導(dǎo)致萬(wàn)向節(jié)鎖。我理解是,當(dāng)依次旋轉(zhuǎn)時(shí),會(huì)出現(xiàn)有個(gè)軸無(wú)法旋轉(zhuǎn),即旋轉(zhuǎn)失效 ,詳細(xì)可查看

Quaternions 四元數(shù)

四元數(shù)也可以用來(lái)表示物體的旋轉(zhuǎn)或者方向,顧名思義,是由四個(gè)數(shù)組成,在Unity3D中是x,y,z,w。不過(guò),這些數(shù)字并不是表示角度和旋轉(zhuǎn)軸,而且你絕不會(huì)直接使用它們。除非你特別想知道四元數(shù)的原理,否則僅僅知道它在3D世界中表示旋轉(zhuǎn)即可,完全不用理解這四個(gè)數(shù)的意義或者嘗試修改它。如果你確實(shí)想了解四元數(shù)的前世今生,詳細(xì)可查看,作者寫的特別詳細(xì)。

好比一個(gè)Vector(矢量)可以表達(dá)位置或者方向(從坐標(biāo)原點(diǎn)看),一個(gè)四元數(shù)也可以同時(shí)表示指向或者旋轉(zhuǎn)角度(從世界坐標(biāo)系的原點(diǎn)或者特定坐標(biāo)系的原點(diǎn)作為參考點(diǎn))。因?yàn)樾D(zhuǎn)是這么計(jì)算的-從一個(gè)方向到另一個(gè)方向,所以一個(gè)四元數(shù)無(wú)法表示一個(gè)超過(guò)180度的旋轉(zhuǎn)。

  • 優(yōu)點(diǎn):無(wú)萬(wàn)向節(jié)鎖
  • 缺點(diǎn):?jiǎn)我凰脑獢?shù)無(wú)法表示任何方向上超過(guò)180度的旋轉(zhuǎn)
  • 缺點(diǎn):四元數(shù)的四個(gè)數(shù)字無(wú)法直觀的理解

權(quán)衡利弊后,在Unity里,所有游戲物體旋轉(zhuǎn)狀態(tài)都是以四元數(shù)的方式存儲(chǔ)的

不過(guò)在Transform的面板中,還是用歐拉角的方式展示數(shù)據(jù),因?yàn)檫@種方式還是更易于理解和編輯。每當(dāng)輸入一個(gè)旋轉(zhuǎn)的值,都會(huì)在后臺(tái)被轉(zhuǎn)存為一個(gè)新的四元數(shù)。

副作用就是,有可能在旋轉(zhuǎn)面板上輸入“X: 0, Y: 365, Z: 0”。這個(gè)歐拉角不可能以四元數(shù)來(lái)表示,所以當(dāng)你點(diǎn)擊"Play",你會(huì)看到面板上的值變成了" X: 0, Y: 5, Z: 0 "(左右)。這是因?yàn)?65度是無(wú)法用四元數(shù)表示的,所以簡(jiǎn)單的用前面的結(jié)果取代了它。

腳本相關(guān)

當(dāng)你在腳本中處理旋轉(zhuǎn)時(shí),你應(yīng)該用到Quaternion類以及它的方法去創(chuàng)建和修改旋轉(zhuǎn)相關(guān)的參數(shù)。有一些場(chǎng)景需要合理的使用歐拉角,但是你要記?。耗銘?yīng)該使用Quaternion類以及方法去處理歐拉角,獲取,修改和重復(fù)使用歐拉值會(huì)出現(xiàn)無(wú)意的副作用。

直接創(chuàng)建和操作四元數(shù)

Unity的Quaternion類有許多創(chuàng)建和操作旋轉(zhuǎn)的方法,這些完全不必用到歐拉角。比如:

  • 創(chuàng)建
    1. Quaternion.LookRotation
    2. Quaternion.AngleAxis
    3. Quaternion.FromToRotation
  • Manipulating:
    1. Quaternion.Slerp
    2. Quaternion.Inverse
    3. Quaternion.RotateTowards
    4. Transform.Rotate & Transform.RotateAround

不過(guò),有時(shí)在你的腳本里使用歐拉角時(shí)合適的。但是需要格外留心的是,用新的變量保存角度,僅僅在需要改變物體旋轉(zhuǎn)時(shí)使用下歐拉角。同時(shí)也有可能從四元數(shù)里獲取當(dāng)前的歐拉角,當(dāng)你獲取,修改,重使用歐拉角時(shí),問(wèn)題就出現(xiàn)了。因?yàn)橹禃?huì)在轉(zhuǎn)化成四元數(shù)時(shí)會(huì)進(jìn)行角度的變化。比如360度和0度之類。。。
以下是一些錯(cuò)誤事例,假設(shè)每秒鐘讓一個(gè)物體繞X軸旋轉(zhuǎn)10度。這是是我們需要避免的:

  1. 錯(cuò)誤一
    直接修改Quaternion的x值,但是這個(gè)值并不是表示角度,所以就不會(huì)產(chǎn)生預(yù)期的結(jié)果
    void Update () {
    
        var rot = transform.rotation;
        rot.x += Time.deltaTime * 10;
        transform.rotation = rot;
        
    }
  1. 錯(cuò)誤二
    讀、寫和修改一個(gè)Quaternion中的歐拉值.因?yàn)檫@些值都是從Quaternion中計(jì)算得出,所以每一次新的旋轉(zhuǎn)可能會(huì)產(chǎn)生極不相同的歐拉角,這有可能引發(fā)萬(wàn)向節(jié)鎖。
    void Update () {
        
        var angles = transform.rotation.eulerAngles;
        angles.x += Time.deltaTime * 10;
        transform.rotation = Quaternion.Euler(angles);

    }
  1. 正確示例
    正確的在腳本中使用歐拉角進(jìn)行旋轉(zhuǎn)。我們使用一個(gè)類成員變量存儲(chǔ)了當(dāng)前的歐拉角,并且只在賦值給Quaternion時(shí)使用,并且不會(huì)從Quaternion中讀取這個(gè)值。
    float x;
    void Update () {
        
        x += Time.deltaTime * 10;
        transform.rotation = Quaternion.Euler(x,0,0);

    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容