游戲開發(fā)中的傾斜相機(jī)鼠標(biāo)旋轉(zhuǎn)實(shí)現(xiàn)

問題的出現(xiàn)
????平常時(shí),游戲相機(jī)正常:也就是如果我們用up-right-forward描述相機(jī)姿態(tài)時(shí),up總是向上,鼠標(biāo)的x,y軸偏移轉(zhuǎn)換成yaw,pitch。

????游戲中很少有roll的偏轉(zhuǎn),或者說不為主要的位姿調(diào)整手段。比如彩虹6號:圍攻(Tom Clancy's Rainbow Six Siege)中的q/e歪頭探頭查看/射擊。

但本篇要講的不是這種歪頭,而是重力方向整個(gè)傾斜:

此時(shí)仍然希望鼠標(biāo)的x,y位移能正確地對相機(jī)進(jìn)行“橫軸”和“縱軸”的旋轉(zhuǎn):

如果還用原來的鼠標(biāo)位移旋轉(zhuǎn)邏輯,相機(jī)會“壞掉”。因?yàn)轱@然此時(shí)相機(jī)的“自然狀態(tài)”(以下我簡稱為0姿態(tài))并非(roll=0,pitch=0,yaw=0)。(類比坐標(biāo)系的變換,此時(shí)我們的“坐標(biāo)系原點(diǎn)”已經(jīng)不在(0,0,0)了,再在其基礎(chǔ)上應(yīng)用基于(0,0,0)的操作是不成立的)
????關(guān)鍵部分只要看Update函數(shù)中的第一行和最后一行,通過鼠標(biāo)的MouseX,MouseY,轉(zhuǎn)換成了相機(jī)的歐拉角的yaw和pitch,注意到eulerAngles.z一直為0,因?yàn)槠匠J遣粫小巴犷^”情況的。
正確計(jì)算旋轉(zhuǎn)
????修復(fù)后的代碼:
????
注意到這幾個(gè)變動:
需要在轉(zhuǎn)換重力方向時(shí),進(jìn)行RecordCamDir,記錄下相機(jī)的新的0姿態(tài):即自然狀態(tài)下的三軸方向和世界旋轉(zhuǎn)。
新的旋轉(zhuǎn)由3部分四元數(shù)相乘,相乘順序不能反,類似矩陣乘法:先是0姿態(tài)的baseRot,然后是“橫軸旋轉(zhuǎn)”dRotX,最后是“豎軸旋轉(zhuǎn)”dRotY。
計(jì)算dRotX時(shí),是以camUp為x旋轉(zhuǎn)軸,而不是(0,1,0);計(jì)算dRotY時(shí),要先根據(jù)當(dāng)前的transform.forward和camUp叉乘出新的y旋轉(zhuǎn)軸,再根據(jù)此軸進(jìn)行旋轉(zhuǎn)(此稱為旋轉(zhuǎn)順規(guī),Unity默認(rèn)順規(guī)為zxy)。并且根據(jù)叉乘計(jì)算dRotY之前,通過對transform.rotation賦值完成了對tranform的更新,否則得不到轉(zhuǎn)完橫軸之后的transform.forward。
