[英]How do I add easing to a scripted transform animation in Unity?
我現在有一個設置,我有一個 3D 對象,在對象內部有一個空對象作為父對象。 當您按下一個按鈕時,相機跟隨的空物體會旋轉 90 度。 如果您按下另一個按鈕,它會將另一個方向旋轉 90 度。 結果是相機可以在物體完全旋轉之前圍繞物體旋轉 4 次。
目前它運行良好,但我試圖弄清楚如何為動畫添加一些緩動,使其看起來不那么粗糙。 我對在動畫中使用曲線有一點了解,但我不確定如何將其應用於代碼(或者它是否是最好的做事方式)
public InputMaster controls;
private bool isSpinning;
private float rotationSpeed = 0.3f;
IEnumerator RotateMe(Vector3 byangles, float intime)
{
var fromangle = transform.rotation;
var toangle = Quaternion.Euler(transform.eulerAngles + byangles);
for (var t = 0f; t < 1; t += Time.deltaTime / intime)
{
transform.rotation = Quaternion.Slerp(fromangle, toangle, t);
yield return null;
transform.rotation = toangle;
}
Debug.Log("finished rotation");
isSpinning = false;
Debug.Log("isSpinning now false");
}
上面的代碼是我創建一個協程的地方,它說明了它將如何轉換。 在這里讓我有點困惑的一件事是,如果我沒有說transform.rotation = toangle;
,旋轉出現在 89.5 度左右,如果你多次這樣做,它會偏離幾度。 不知道為什么會這樣。
void Rotation(float amount)
{
Debug.Log("rotation number is " + amount);
float holdingRotate = controls.Player.Camera.ReadValue<float>();
if (holdingRotate == 1 && isSpinning == false)
{
isSpinning = true;
Debug.Log("isSpinning now true");
StartCoroutine(RotateMe(Vector3.up * 90, rotationSpeed));
}
else if (holdingRotate == -1 && isSpinning == false)
{
isSpinning = true;
Debug.Log("isSpinning now true");
StartCoroutine(RotateMe(Vector3.up * -90, rotationSpeed));
}
}
這部分是調用動畫的地方。 非常感謝任何幫助。
看看@immersive 所說的動畫曲線。
只需將其添加到代碼中,您就可以輕松地在檢查器中定義自己的曲線:
public AnimationCurve curve;
然后您可以使用AnimationCurve.Evaluate對曲線進行采樣。
另一種方法是使用 AssetStore/Package Manager 中的預制庫,如 DOTween 或 LeanTween 來命名一些。
for (var t = 0f; t < 1; t += Time.deltaTime / intime)
{
transform.rotation = Quaternion.Slerp(fromangle, toangle, t);
yield return null;
}
transform.rotation = toangle;
因為t
不會等於 1。
您只需要在循環后將旋轉設置為目標。
內聯評論:
public class SmoothRotator : MonoBehaviour
{
// Animation curve holds the 'lerp factor' from starting angle to final angle over time
// (Y axis is blend factor, X axis is normalized 'time' factor)
public AnimationCurve Ease = AnimationCurve.EaseInOut(0, 0, 1, 1);
public float Duration = 1f;
private IEnumerator ActiveCoroutine = null;
public void RotateToward(Quaternion targetAngle) {
// If there's a Coroutine to stop, stop it.
if (ActiveCoroutine != null)
StopCoroutine(ActiveCoroutine);
// Start new Coroutine and cache the IEnumerator in case we need to interrupt it.
StartCoroutine(ActiveCoroutine = Rotator(targetAngle));
}
public IEnumerator Rotator(Quaternion targetAngle) {
// Store starting angle
var fromAngle = transform.rotation;
// Accumulator for Time.deltaTime
var age = 0f;
while (age < 1f) {
// normalize time (scale to "percentage complete") and clamp it
var normalisedTime = Mathf.Clamp01(age / Duration);
// Pull lerp factor from AnimationCurve
var lerpFactor = Ease.Evaluate(normalisedTime);
// Set rotation
transform.rotation = Quaternion.Slerp(fromAngle, targetAngle, lerpFactor);
// Wait for next frame
yield return null;
// Update age with new frame's deltaTime
age += Time.deltaTime;
}
// Animation complete, force true value
transform.rotation = targetAngle;
// Housekeeping, clear ActiveCoroutine
ActiveCoroutine = null;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.