我有一個腳本,我希望在 X 軸上旋轉某些東西,并且我希望其他兩個軸保持不變而不被修改(它們在 0 和 180 之間翻轉),并且只有 X 可以改變。
您可以在下面看到旨在執行此操作的代碼。
public class TestScript : MonoBehaviour
{
private void Start()
{
//this line is meant to show that I'm reseting the rotation before starting
transform.eulerAngles = Vector3.zero;
Debug.Log($"start rotation: {transform.eulerAngles}");
}
private void Update()
{
float time = (Time.time - 1f) * 10f;
if (time < 0f || time > 1f)
{
return;
}
Vector3 rotation = transform.eulerAngles;
float x = Mathf.Lerp(170f, 0, time);
rotation.x = x;
transform.eulerAngles = rotation;
Debug.Log($"rotation: {transform.eulerAngles}, x: {x}");
}
}
控制臺的輸出。您可以清楚地看到旋轉不是從 170 到 0,而是從 0 到 90 再回到 0。

現在,我很確定這與四元數及其身份有關,但不確定如何避免這種情況
PS:在你回答之前,請閱讀此內容
- 我不想使用 Vector 來旋轉整個物件。我只想一次旋轉一個軸。
- I know that this is due to the fact that quaternions represent a rotation, and there are multiple ways to represent a rotation when converting into euler angles, but that doesn't help me, because I do only want to do one axis rotation and the others not to be modified. At all.
- I'm actually trying to do this for the other 2 axes too.
- The rotation has to be from one value to another during a specific period of time, rather than rotate a certain amount over an unspecified amount of time.
- This script is not actually what I'm trying to achieve but a simplified version of my issue. If any of this is not that clear, check these 2 scripts, where I'm actually trying to achieve this. Abstract Axis Rotate
uj5u.com熱心網友回復:
我會存盤一個Vector3所有 1-3個TestScript品種都可以查看和編輯它的地方,這樣就沒有Transform一個以上的 vector3 與之關聯。例如,這可以存盤在字典中,其中每個 Transform 都可以用作鍵。還有其他方法可以做到這一點,但這超出了范圍。cache為簡單起見,我將呼叫此 vector3 的值。
對于每個腳本,您還需要一種方法來確定歐拉角的哪些分量不受控制。這可以以類似于的方式完成cache,如何實作也超出了這個問題的范圍。
進行每次TestScript更新cache,以便將其控制的矢量分量設定為其當前插值。然后讓每個組件將其分配cache給eulerAngles,或者可選地,只讓最后一個組件TestScript進行分配。
就你的問題而言,一個很好的問題,順便說一句,我會說 181、0、360。我真的不在乎你對其他軸做了什么,以及你的四元數是否會擾亂旋轉。
由于您希望此內部狀態向量在發生任何外部變化時不會覆寫不受控制的向量分量,因此您可以執行以下操作:
當TestScript幀中的第一個變體執行時,比較(使用例如Quaternion.Angle(a,b) < 0.00001f,使其將 540,0,0 與 180,0,0 視為相同)變換的電流rotation與 產生的四元數Quaternion.Euler(cache)。如果確定旋轉不同,則將變換的不受控制的組件分配eulerAngles給cache,然后繼續通常的操作。
偽代碼,underscore_case 的東西是非常偽的:
Transform myTransform;
Vector3 startEulers = myTransform.eulerAngles;
Vector3 cache = get_cache(myTransform);
if (is_this_TestScript_first_to_go_this_frame())
{
if (Quaternion.Angle(myTransform.rotation, Quaternion.Euler(cache)) < 0.0001f)
{
if (is_x_uncontrolled(myTransform))
cache.x = startEulers.x;
if (is_y_uncontrolled(myTransform))
cache.y = startEulers.y;
if (is_z_uncontrolled(myTransform))
cache.z = startEulers.z;
set_cache(myTransform, cache);
}
}
switch(my_axis)
{
case X:
cache.x = get_current_interp_val();
break;
case Y:
cache.y = get_current_interp_val();
break;
case Z:
cache.z = get_current_interp_val();
break;
default:
throw exception;
}
myTransform.eulerAngles = cache;
這會讓你開始朝著你想要的方向前進。
uj5u.com熱心網友回復:
由于 Unity 解釋四元數的方式,這無法實作。如果你想這樣做,你可能想走不同的路線。transform.Rotate(Vector3) 對我有用。這不是我正在使用的解決方案,但這是我最初發布的腳本必須修改以實作相同目的的方式。
public class TestScript : MonoBehaviour
{
private float lastX;
private void Start()
{
transform.eulerAngles = Vector3.zero;
lastX = transform.eulerAngles.x;
Debug.Log($"start rotation: {transform.eulerAngles}");
}
private void Update()
{
float time = Time.time - 1f;
if (time < 0 || time > 1f)
{
return;
}
float x = Mathf.Lerp(0f, -170f, time);
Vector3 rotation = new Vector3(x - lastX, 0f, 0f);
lastX = x;
transform.Rotate(rotation);
Debug.Log($"rotation: {transform.eulerAngles}, x: {x}");
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/416073.html
標籤:
上一篇:每波增加敵人的生命值
