- Home /
Evaluating animation curves in the Timeline
Is there a way to sample animation curves displayed in the Timeline panel for specific objects and at specific frames/times?
For example I've hand animated an object and can playback the animation using the play button in the "new" Timeline panel in Editor mode (not Game mode). I can then click the curves icon and see the animation curves. I want to write an editor script that can poll, for instance, the rotateY value at frame 30 or at time 1.0 regardless if a keyframe exists there or not (i.e. the value would be interpolated if not a defined keyframe).
Answer by seant_unity · Oct 29, 2018 at 11:24 AM
You can search through the timeline asset to find the clip(s) you need to sample. Then use the AnimationUtility methods to get the curves you are looking for.
For example:
public static AnimationClip FindClipAtTime(TimelineAsset timeline, string nameOfTrackToFind, double time)
{
foreach (var track in timeline.GetOutputTracks())
{
// find track name
if (track.name == nameOfTrackToFind)
{
foreach (var clip in track.GetClips())
{
if (clip.start >= time && clip.end <= time)
{
var asset = clip.asset as AnimationPlayableAsset;
if (asset != null)
return asset.clip;
}
}
}
}
return null;
}
Thanks so much for the help! I've now the output I need based on your example. There are a few oddities:
there's no way to get an individual curve binding, rather (similar to your sample code) you have to iterate over all bindings comparing to the name of the one you want
the actual curve names are not what I expected, i.e. "localEulerAnglesRaw.y" ins$$anonymous$$d of "rotation.y" (but I guess they're differentiating between the internally stored quaternion value as opposed to the revealved Euler values)
there is a "SampleAnimation" method in the AnimationClip class but that seems to require an actual GameObject ins$$anonymous$$d of an AnimationCurve.
It seems a little convoluted and I'm not sure that what I have now is the best approach for what I'm trying to do
For reference here is the code I came up with to sample a specified curve's values over a time range via references from a Timeline's initial track/clip with an associated editor script with a button to execute the ExportData method so that it's all being run in Editor $$anonymous$$ode.:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Timeline;
using UnityEditor;
public class DataExport : $$anonymous$$onoBehaviour {
public TimelineAsset timeline;
public string trackName;
public float timeStart = 0f;
public float timeEnd = 0f;
public float timeStep = 0.12f;
private TrackAsset track;
public void ExportData() {
track = timeline.GetOutputTrack(0);
foreach (var clip in track.GetClips()) {
var asset = clip.asset as AnimationPlayableAsset;
var assetClip = asset.clip;
foreach (var binding in AnimationUtility.GetCurveBindings(assetClip)) {
if (binding.propertyName == trackName) {
AnimationCurve curve = AnimationUtility.GetEditorCurve(assetClip, binding);
for (float t = timeStart; t < timeEnd; t+= timeStep)
Debug.LogWarning("t = " + t + ":\tv = " + curve.Evaluate(t));
}
}
}
}
}