Why are Animated Clip data always returning null curve and clip definitions? 2017.3.1f1

Hello,

I’m hoping to probe Unity animation keyframe data using C#. I’ve tried accessing keyframes from TimelineClip and AnimationClip data at my scene, but the ‘curve’ and ‘clip’ data on these objects always appear null/empty.

I’m not expecting null data, because curve and keyframe data are added to the scene and they are visible in the Unity GUI Timeline and Curve editing windows.

To add the curves I created a new Timeline/Director and used the ‘record’ button to change the mesh positions at points on the timeline. When recording was stopped, I right-click converted the track to “Animation Clip”.

What I’m doing wrong? How can I access keyframe data? Why are curve data on my TimelineClip instances null?

The function I’m using to Log the Timeline data

    public static void accessTimeline ()
    {
        UnityEngine.SceneManagement.Scene scene = UnityEngine.SceneManagement.SceneManager.GetActiveScene();
        IList<GameObject> sceneObjects = scene.GetRootGameObjects();
        string logstr = "timeline, ";

        logstr += "\n scene: " + scene.name + " type: " + scene.GetType().Name;
        foreach (GameObject g in sceneObjects)
        {
            PlayableDirector director = g.GetComponent<PlayableDirector>();
            logstr += "\n      * object: " + g.name + " type: " + g.GetType().Name + " isdirectory?:" + (director != null);
            if (director != null)
            {
                TimelineAsset timelineAsset = director.playableAsset as TimelineAsset;
                if (timelineAsset == null)
                    continue;

                IEnumerable<UnityEngine.Timeline.TrackAsset> tracks = timelineAsset.GetOutputTracks();
                logstr += "\n            timelineAsset: " + timelineAsset.name;

                foreach (var track in timelineAsset.GetOutputTracks())
                {
                    var animTrack = track as AnimationTrack;
                    if (animTrack == null)
                        continue;

                    var binding = director.GetGenericBinding(animTrack);
                    if (binding == null)
                        continue;
                    var animator = binding as Animator;
                    var gameObject = binding as GameObject;
                    if (animator == null && gameObject != null)
                        animator = gameObject.GetComponent<Animator>();
                    if (animator == null)
                        continue;

                    foreach (var clips in animTrack.GetClips())
                    {
                        var animAsset = clips.asset as AnimationPlayableAsset;
                        if (animAsset)
                        {
                            AnimationClip clip = animAsset.clip;
                            logstr += "\n                     animationTrack is (w/ animator): curves: " + UnityEditor.AnimationUtility.GetAllCurves(clip);
                            // ...
          
                        }
                    } 
                }

                // get curves from trackAsset TimelineClips
                foreach (UnityEngine.Timeline.TrackAsset trackAsset in tracks)
                {
                    IEnumerable<UnityEngine.Timeline.TrackAsset> childtracks = trackAsset.GetChildTracks();

                    logstr += "\n                 trackAsset: " + trackAsset.start + "-" + trackAsset.end
                        + " " + trackAsset.name + " " + trackAsset.outputs + " childtracks: " + childtracks;

                    IEnumerable<UnityEngine.Timeline.TimelineClip> clips = trackAsset.GetClips();

                    foreach (UnityEngine.Timeline.TimelineClip trackAssetClip in clips)
                    {
                        AnimationClip curves = trackAssetClip.curves;

                        logstr += "\n                       trackAssetClip: " + trackAssetClip.animationClip + " " +
                            + trackAssetClip.start + "-" + trackAssetClip.end + ":  " +
                            trackAssetClip.animationClip;

                        if (curves == null)
                            logstr += "\n                              curves: null";
                        else
                            logstr += "\n                              curves: " + curves.events;
                    }
                }
            }
        }

        Debug.Log(logstr);
    }

Attached is a screenshot of tracks with recorded animation points at the logged scene - the Debug.Log prints trackAssetClip data, but curves are null.

TimelineClip.curves is where animation data is stored when animating playable parameters. That’s used for animating parameters on custom clips.

trackAssetClip.animationClip is the animation clip you want in this case. It’s just a shortcut for (trackAssetClip.asset as AnimationPlayableAsset).animClip.