Baking Unity Animation Curves
雖然Quantum的FPAnimationCurve
本質上已經透過曲線編輯器,在Unity的非確定性類型之間進行了轉換,有時候在編輯器中沒有可用的自動轉換時,從一個AnimationCurve
轉換可能相當有用。
一個示例是來自Unity動畫片段的曲線的轉換,以建立可用於模擬的確定性版本。
這裡是從一個AnimationCurve
來建立一個FPAnimationCurve
所需的程式碼片段:
C#
public FPAnimationCurve ConvertAnimationCurve(AnimationCurve animationCurve)
{
// Get UNITY keyframes
Keyframe[] unityKeys = animationCurve.keys;
// Prepare QUANTUM curves and keyframes to receive the info
FPAnimationCurve fpCurve = new FPAnimationCurve();
fpCurve.Keys = new FPAnimationCurve.Keyframe[unityKeys.Length];
// Get the Unity Start and End time for this specific curve
float startTime = animationCurve.keys.Length == 0 ? 0.0f : float.MaxValue;
float endTime = animationCurve.keys.Length == 0 ? 1.0f : float.MinValue;
// Set the resolution for the curve, which informs how detailed it is
fpCurve.Resolution = 32;
for (int i = 0; i < unityKeys.Length; i++)
{
fpCurve.Keys[i].Time = FP.FromFloat_UNSAFE(unityKeys[i].time);
fpCurve.Keys[i].Value = FP.FromFloat_UNSAFE(unityKeys[i].value);
if (float.IsInfinity(unityKeys[i].inTangent) == false)
{
fpCurve.Keys[i].InTangent = FP.FromFloat_UNSAFE(unityKeys[i].inTangent);
}
else
{
fpCurve.Keys[i].InTangent = FP.SmallestNonZero;
}
if (float.IsInfinity(unityKeys[i].outTangent) == false)
{
fpCurve.Keys[i].OutTangent = FP.FromFloat_UNSAFE(unityKeys[i].outTangent);
}
else
{
fpCurve.Keys[i].OutTangent = FP.SmallestNonZero;
}
fpCurve.Keys[i].TangentModeLeft = (byte)AnimationUtility.GetKeyLeftTangentMode(animationCurve, i);
fpCurve.Keys[i].TangentModeRight = (byte)AnimationUtility.GetKeyRightTangentMode(animationCurve, i);
startTime = Mathf.Min(startTime, animationCurve[i].time);
endTime = Mathf.Max(endTime, animationCurve[i].time);
}
fpCurve.StartTime = FP.FromFloat_UNSAFE(startTime);
fpCurve.EndTime = FP.FromFloat_UNSAFE(endTime);
fpCurve.PreWrapMode = (int)animationCurve.preWrapMode;
fpCurve.PostWrapMode = (int)animationCurve.postWrapMode;
// Actually save the many points of the unity curve into the quantum curve
SaveQuantumCurve(animationCurve, 32, ref fpCurve, startTime, endTime);
return fpCurve;
}
private void SaveQuantumCurve(AnimationCurve animationCurve, int resolution, ref FPAnimationCurve fpCurve, float startTime, float endTime)
{
if (resolution <= 0)
return;
fpCurve.Samples = new FP[resolution + 1];
var deltaTime = (endTime - startTime) / (float)resolution;
for (int i = 0; i < resolution + 1; i++)
{
var time = startTime + deltaTime * i;
var fp = FP.FromFloat_UNSAFE(animationCurve.Evaluate(time));
fpCurve.Samples[i].RawValue = fp.RawValue;
}
}
Back to top