/// <summary>Evaluates the resulting value of a TransformConstraintTimeline at a given time.
/// SkeletonData can be accessed from Skeleton.Data or from SkeletonDataAsset.GetSkeletonData.
/// If no SkeletonData is given, values are computed relative to setup pose instead of local-absolute.</summary>
public static Vector2 Evaluate(this TransformConstraintTimeline timeline, float time, TransformConstraint transformConstraint)
{
var frames = timeline.frames;
if (time < frames[0]) return Vector2.zero;
if (transformConstraint == null) return Vector2.zero;
int i = Timeline.Search(frames, time, TransformConstraintTimeline.ENTRIES);
int curveType = (int)timeline.curves[i / TransformConstraintTimeline.ENTRIES];
float translateMixX, translateMixY;
switch (curveType)
{
case CurveTimeline.LINEAR:
float before = frames[i];
translateMixX = frames[i + TransformConstraintTimeline.X];
translateMixY = frames[i + TransformConstraintTimeline.Y];
float t = (time - before) / (frames[i + TransformConstraintTimeline.ENTRIES] - before);
translateMixX += (frames[i + TransformConstraintTimeline.ENTRIES + TransformConstraintTimeline.X] - translateMixX) * t;
translateMixY += (frames[i + TransformConstraintTimeline.ENTRIES + TransformConstraintTimeline.Y] - translateMixY) * t;
break;
case CurveTimeline.STEPPED:
translateMixX = frames[i + TransformConstraintTimeline.X];
translateMixY = frames[i + TransformConstraintTimeline.Y];
break;
default:
translateMixX = timeline.GetBezierValue(time, i, TransformConstraintTimeline.X, curveType - CurveTimeline.BEZIER);
translateMixY = timeline.GetBezierValue(time, i, TransformConstraintTimeline.Y, curveType + CurveTimeline.BEZIER_SIZE - CurveTimeline.BEZIER);
break;
}
return new Vector2(transformConstraint.target.x * translateMixX, transformConstraint.target.y * translateMixY);
}
public static TransformConstraintTimeline FindTransformConstraintTimeline(this Animation a, int transformConstraintIndex)
{
foreach (var timeline in a.timelines)
{
if (timeline.GetType().IsSubclassOf(typeof(TransformConstraintTimeline)))
continue;
var transformConstraintTimeline = timeline as TransformConstraintTimeline;
if (transformConstraintTimeline != null && transformConstraintTimeline.TransformConstraintIndex == transformConstraintIndex)
return transformConstraintTimeline;
}
return null;
}
It surprised me that the standard rootmotion implementation was unable to handle this./// SkeletonData can be accessed from Skeleton.Data or from SkeletonDataAsset.GetSkeletonData.
/// If no SkeletonData is given, values are computed relative to setup pose instead of local-absolute.</summary>
public static Vector2 Evaluate(this TransformConstraintTimeline timeline, float time, TransformConstraint transformConstraint)
{
var frames = timeline.frames;
if (time < frames[0]) return Vector2.zero;
if (transformConstraint == null) return Vector2.zero;
int i = Timeline.Search(frames, time, TransformConstraintTimeline.ENTRIES);
int curveType = (int)timeline.curves[i / TransformConstraintTimeline.ENTRIES];
float translateMixX, translateMixY;
switch (curveType)
{
case CurveTimeline.LINEAR:
float before = frames[i];
translateMixX = frames[i + TransformConstraintTimeline.X];
translateMixY = frames[i + TransformConstraintTimeline.Y];
float t = (time - before) / (frames[i + TransformConstraintTimeline.ENTRIES] - before);
translateMixX += (frames[i + TransformConstraintTimeline.ENTRIES + TransformConstraintTimeline.X] - translateMixX) * t;
translateMixY += (frames[i + TransformConstraintTimeline.ENTRIES + TransformConstraintTimeline.Y] - translateMixY) * t;
break;
case CurveTimeline.STEPPED:
translateMixX = frames[i + TransformConstraintTimeline.X];
translateMixY = frames[i + TransformConstraintTimeline.Y];
break;
default:
translateMixX = timeline.GetBezierValue(time, i, TransformConstraintTimeline.X, curveType - CurveTimeline.BEZIER);
translateMixY = timeline.GetBezierValue(time, i, TransformConstraintTimeline.Y, curveType + CurveTimeline.BEZIER_SIZE - CurveTimeline.BEZIER);
break;
}
return new Vector2(transformConstraint.target.x * translateMixX, transformConstraint.target.y * translateMixY);
}
public static TransformConstraintTimeline FindTransformConstraintTimeline(this Animation a, int transformConstraintIndex)
{
foreach (var timeline in a.timelines)
{
if (timeline.GetType().IsSubclassOf(typeof(TransformConstraintTimeline)))
continue;
var transformConstraintTimeline = timeline as TransformConstraintTimeline;
if (transformConstraintTimeline != null && transformConstraintTimeline.TransformConstraintIndex == transformConstraintIndex)
return transformConstraintTimeline;
}
return null;
}