Unity中設定Transform的forward/up/right旋轉異常問題
本文首發於洪流學堂微信公眾號。
洪流學堂公眾號回覆forward
,獲取本文的測試工程。
小新:“智哥,我在設定人物持槍IK時,想要將槍的方向設定為游標的方向。但是出現了槍旋轉混亂的問題,這個該怎麼解決啊?”
大智:“具體說說看你是怎麼實現的?”
小新:“我先計算了槍的朝向的向量,程式碼是這樣的”
想深入瞭解大智和小新這對好基友,可以在洪流學堂公眾號回覆
小新
瞭解他們。
var pos = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width / 2, Screen.height / 2, 10));
var direction = (pos - _currentGun.transform.position).normalized;
小新:“這不計算出來方向了嘛,我覺得最簡單的方法就是設定槍的transform裡面的forward向量。但是我先設定場景為pivot模式(顯示物體的自身座標軸),然後看了槍的軸以後,發現槍口方向的軸不是forward,而是紅色的軸,也就是right。”
大智:“沒錯,這點很好,就是不要想當然的用forward/up/right這些軸,一定要根據實際情況。forward是藍色的軸,up是綠色的軸,right是紅色的軸。記不清楚的時候可以看下Scene視窗右上角的小工具的顏色。”
小新:“然後我就設定槍的transform的right為-direction,就像這樣”
_currentGun.transform.right = -direction;
小新:“結果執行起來是這個樣子,上下旋轉沒啥問題,但是左右旋轉槍會發生翻轉”
大智:“好,我大概瞭解了。你使用了transform的right屬性,但是你知不知道設定right的具體內部程式碼是什麼?”
小新:“這個我還真不知道”
大智:“Unity已經公佈了C#端的所有原始碼,這個你可以去 https://github.com/Unity-Technologies/UnityCsReference
小新趕忙開啟這個連結,去找相關的內容。
小新:“在Github網站上找好麻煩,我還是把它下載下來”
大智:“非常明智,下載下來以後通過VS開啟可以快速找到想要的內容”
小新:“找到了!在Transform.bindings.cs檔案的第41行”
// The red axis of the transform in world space.
public Vector3 right { get { return rotation * Vector3.right; } set { rotation = Quaternion.FromToRotation(Vector3.right, value); } }
// The green axis of the transform in world space.
public Vector3 up { get { return rotation * Vector3.up; } set { rotation = Quaternion.FromToRotation(Vector3.up, value); } }
// The blue axis of the transform in world space.
public Vector3 forward { get { return rotation * Vector3.forward; } set { rotation = Quaternion.LookRotation(value); } }
大智:“你仔細看看這三個屬性在set的時候內部具體是如何實現的”
小新:“對於right和up,他用了Quaternion.FromToRotation來建立了一個四元數,但是起始位置用的是世界座標軸的right和up”
大智:“沒錯,起始位置用的是世界座標軸的right和up,而槍的初始姿態不正常,因為是平躺在地上的而不是豎著的狀態,需要將槍的朝向調整為拿在手中時的朝向,比如將槍調成豎著的狀態。對於這個槍Quaternion.FromToRotation在計算旋轉的時候就會出現不正常的情況。這時候有兩種解決方式:”
- 通過給槍加一個空的父物體,調整好槍的朝向,使用這個父節點進行旋轉,這樣槍就不會沿著x軸旋轉了,旋轉也就正確了。
- 不使用transform的right進行設定,而是自己計算旋轉。程式碼也很簡單,如下:
var rot = Quaternion.FromToRotation(-_currentGun.transform.right, direction);
_currentGun.transform.rotation = rot * _currentGun.transform.rotation;
大智:“這種方式在物體原來旋轉的基礎上進行旋轉疊加,不會出現旋轉亂掉的問題。”
總結
小新:“以後再遇到問題我要探究問題的深層次原因,不能僅限於將問題解決這個表象。”
大智:“這麼想就對了,這樣才能進步的更快!”
今日思考題
下載測試工程,深入瞭解下這個問題的原因和解決辦法吧!
洪流學堂公眾號回覆forward
,獲取本文的測試工程。
歡迎在留言區分享你的收穫,和大家一起討論。
別忘了分享給你學Unity的朋友,也許能夠幫到他。
《鄭洪智的Unity2018課》,傾盡我8年的開發經驗,結合最新的Unity2018,帶你從入門到精通。