Files
2026-03-04 10:03:45 +08:00

144 lines
3.8 KiB
C#

using System;
using UnityEngine;
namespace RootMotion
{
[Serializable]
public class BakerTransform
{
public Transform transform;
public AnimationCurve posX;
public AnimationCurve posY;
public AnimationCurve posZ;
public AnimationCurve rotX;
public AnimationCurve rotY;
public AnimationCurve rotZ;
public AnimationCurve rotW;
private string relativePath;
private bool recordPosition;
private Vector3 relativePosition;
private bool isRootNode;
private Quaternion relativeRotation;
public BakerTransform(Transform transform, Transform root, bool recordPosition, bool isRootNode)
{
this.transform = transform;
this.recordPosition = recordPosition || isRootNode;
this.isRootNode = isRootNode;
relativePath = string.Empty;
Reset();
}
public void SetRelativeSpace(Vector3 position, Quaternion rotation)
{
relativePosition = position;
relativeRotation = rotation;
}
public void SetCurves(ref AnimationClip clip)
{
if (recordPosition)
{
clip.SetCurve(relativePath, typeof(Transform), "localPosition.x", posX);
clip.SetCurve(relativePath, typeof(Transform), "localPosition.y", posY);
clip.SetCurve(relativePath, typeof(Transform), "localPosition.z", posZ);
}
clip.SetCurve(relativePath, typeof(Transform), "localRotation.x", rotX);
clip.SetCurve(relativePath, typeof(Transform), "localRotation.y", rotY);
clip.SetCurve(relativePath, typeof(Transform), "localRotation.z", rotZ);
clip.SetCurve(relativePath, typeof(Transform), "localRotation.w", rotW);
if (isRootNode)
{
AddRootMotionCurves(ref clip);
}
clip.EnsureQuaternionContinuity();
}
private void AddRootMotionCurves(ref AnimationClip clip)
{
if (recordPosition)
{
clip.SetCurve("", typeof(Animator), "MotionT.x", posX);
clip.SetCurve("", typeof(Animator), "MotionT.y", posY);
clip.SetCurve("", typeof(Animator), "MotionT.z", posZ);
}
clip.SetCurve("", typeof(Animator), "MotionQ.x", rotX);
clip.SetCurve("", typeof(Animator), "MotionQ.y", rotY);
clip.SetCurve("", typeof(Animator), "MotionQ.z", rotZ);
clip.SetCurve("", typeof(Animator), "MotionQ.w", rotW);
}
public void Reset()
{
posX = new AnimationCurve();
posY = new AnimationCurve();
posZ = new AnimationCurve();
rotX = new AnimationCurve();
rotY = new AnimationCurve();
rotZ = new AnimationCurve();
rotW = new AnimationCurve();
}
public void ReduceKeyframes(float maxError)
{
BakerUtilities.ReduceKeyframes(rotX, maxError);
BakerUtilities.ReduceKeyframes(rotY, maxError);
BakerUtilities.ReduceKeyframes(rotZ, maxError);
BakerUtilities.ReduceKeyframes(rotW, maxError);
BakerUtilities.ReduceKeyframes(posX, maxError);
BakerUtilities.ReduceKeyframes(posY, maxError);
BakerUtilities.ReduceKeyframes(posZ, maxError);
}
public void SetKeyframes(float time)
{
if (recordPosition)
{
Vector3 vector = transform.localPosition;
if (isRootNode)
{
vector = transform.position - relativePosition;
}
posX.AddKey(time, vector.x);
posY.AddKey(time, vector.y);
posZ.AddKey(time, vector.z);
}
Quaternion quaternion = transform.localRotation;
if (isRootNode)
{
quaternion = Quaternion.Inverse(relativeRotation) * transform.rotation;
}
rotX.AddKey(time, quaternion.x);
rotY.AddKey(time, quaternion.y);
rotZ.AddKey(time, quaternion.z);
rotW.AddKey(time, quaternion.w);
}
public void AddLoopFrame(float time)
{
if (recordPosition && !isRootNode)
{
posX.AddKey(time, posX.keys[0].value);
posY.AddKey(time, posY.keys[0].value);
posZ.AddKey(time, posZ.keys[0].value);
}
rotX.AddKey(time, rotX.keys[0].value);
rotY.AddKey(time, rotY.keys[0].value);
rotZ.AddKey(time, rotZ.keys[0].value);
rotW.AddKey(time, rotW.keys[0].value);
}
}
}