每次按空格鍵時,我都試圖將立方體平滑地旋轉 90 度。在我的代碼中,每次我將速度降低到小于 1 時,它的旋轉在 90 度下降時不一致,而速度超過 1 時,它的旋轉立即不順暢。這是我的代碼
Vector3 to = new Vector3(0, 0, 90);
public float speed = 0.5f;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
RotateOne();
}
}
void RotateOne()
{
transform.eulerAngles = Vector3.Lerp(transform.rotation.eulerAngles, to, speed * Time.deltaTime);
to = new Vector3(0, 0, 90);
}
uj5u.com熱心網友回復:
你幾乎擁有它;)
主要問題是,當您單擊該鍵時,您只旋轉了一點點。
您寧愿連續旋轉,單擊時只增加一次目標旋轉。
第二個問題是您使用eulerAngles連續旋轉。從 API:
使用 .eulerAngles 屬性設定旋轉時,請務必了解,盡管您提供 X、Y 和 Z 旋轉值來描述旋轉,但這些值不會存盤在旋轉中。相反,X、Y 和 Z 值被轉換為四元數的內部格式。
當您閱讀 .eulerAngles 屬性時,Unity 會將四元數的內部旋轉表示轉換為歐拉角。因為,使用歐拉角表示任何給定旋轉的方法不止一種,因此您讀出的值可能與您分配的值完全不同。如果您嘗試逐漸增加值以生成影片,這可能會導致混淆。
為避免此類問題,推薦使用旋轉的方法是在讀取 .eulerAngles 時避免依賴一致的結果,尤其是在嘗試逐漸增加旋轉以產生影片時。有關實作此目的的更好方法,請參閱
Quaternion * operator.
// In general instead of eulerAngles always prefer calculating with
// Quaternion directly where possible
private Quaternion to;
void Start()
{
to = transform.rotation;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
RotateOne();
}
// You want to do this always, not only in the one frame the key goes down
// Rather use RotateTowards for a linear rotation speed (angle in degrees per second!)
transform.rotation = Quaternion.RotateTowards(transform.rotation, to, speed * Time.deltaTime);
// Or if you still rather want to interpolate
//transform.rotation = Quaternion.Lerp(transform.rotation, to, speed * Time.deltaTime);
}
void RotateOne()
{
to *= Quaternion.Euler(0, 0, 90);
}
請注意,雖然這會有一個小問題:當你擊鍵 3 或 4 次時,它會突然旋轉回來!這是因為RotateTowards和Lerp使用兩者都以最短的方式朝向目標旋轉。
為了在您的情況下完全避免這種情況,您可以使用Corotuine并堆疊您的輸入,例如
private int pendingRotations;
private bool isRotating;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
pendingRotations ;
if(!isRotating) StartCoroutine(RotateRoutine());
}
}
IEnumerator RotateRoutine()
{
// just in case
if(isRotating) yield break;
isRotating = true;
var targetRotation = transform.rotation * Quaternion.Euler(0, 0, 90);
while (transform.rotation != targetRotation)
{
transform.rotation = Quaternion.RotateTowards(startRotation, targetRotation, speed * Time.deltaTime);
// tells Unity to "pause" the routine here, render this frame
// and continue from here in the next fame
yield return null;
}
// in order to end up with a clean value
transform.rotation = targetRotation;
isRotating = false;
pendingRotations--;
// are there more rotations pending?
if (pendingRotations > 0)
{
// start another routine
StartCoroutine(RotateRoutine());
}
}
uj5u.com熱心網友回復:
Quaternion to = Quaternion.Euler(0,0,90);
transform.rotation = Quaternion.Lerp(transform.rotation, to, speed * Time.deltaTime);
不要更改to并添加 Time.deltaTime
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/440947.html
