1. 程式人生 > >Unity中設定Transform的forward/up/right旋轉異常問題

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視窗右上角的小工具的顏色。”

Scene視窗右上角的小工具

小新:“然後我就設定槍的transform的right為-direction,就像這樣”

_currentGun.transform.right = -direction;

小新:“結果執行起來是這個樣子,上下旋轉沒啥問題,但是左右旋轉槍會發生翻轉”

槍會發生翻轉.gif

大智:“好,我大概瞭解了。你使用了transform的right屬性,但是你知不知道設定right的具體內部程式碼是什麼?”

小新:“這個我還真不知道”

大智:“Unity已經公佈了C#端的所有原始碼,這個你可以去 https://github.com/Unity-Technologies/UnityCsReference

裡面檢視。你去看看Transform類中的forward/up/right是怎麼定義的”

小新趕忙開啟這個連結,去找相關的內容。

小新:“在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,帶你從入門到精通。