noob question on Timeline - Get GameObject reference from a Timeline track

hey folks, i’ve searched a bunch on the web and in this forum for the answer to a simple question. i just need to get the reference to a GameObject that is associated with a particular track binding on a TimelineAsset.

i’ve been able to get to the points of using TimelineAsset.GetOutputTrack(track number), which gets me a TrackAsset, and then i can get the outputs from that track. but the output is in PlayableBinding format.

for (int trackCount=0; trackCount < currList.Length; trackCount++)
        {
            //set bound GameObject to each associated GameObject in track
            TrackAsset trackAsset = timeline.GetOutputTrack(trackCount);

            //this is what i don't know
            GameObject boundGameObj = trackAsset.outputs.sourceObject.GameObject ?

            currList[trackCount].m_boundGameObject = boundGameObj;
        }

i don’t know whether ‘outputs’ is a list of items, and then i also don’t know how to access an actual UnityEngine.GameObject class from that UnityObject class.

i’m sure there’s something i’m not seeing in terms of documentation but that’s my main issue so far. using Unity 2019.3 BTW. help appreciated!

scott

The PlayableDirector (i.e. the timeline player) holds the bindings of gameObjects (or components) to tracks.

You can use PlayableDirector.GetGenericBinding(track) to retrieve the binding. The return value needs to be cast to the appropriate type, like Animator for AnimationTracks, GameObject for ActivationTracks, etc…

what i want to do is get the Transform or GameObject reference from any GenericBinding method, on a AudioTrack. i want to find out the GameObject/Transform associated with that binding’s AudioSource. i can’t find an example of how that type of casting is done. if you could give an example or show me an example of casting in the docs? i’m not as familiar on C# structure in these certain areas. mostly familiar with casting between ints, floats and strings.

thanks!

Sure. Here’s a method that will return you the transform component of the binding, given a PlayableDirector and a Track of any type, including Audio.

        public static Transform GetTransformBinding(PlayableDirector director, TrackAsset track)
        {
            if (director == null)
                return null;

            var binding = director.GetGenericBinding(track);
            if (binding is Component)
                return ((Component) binding).transform;

            if (binding is GameObject)
                return ((GameObject) binding).transform;

            return null;
        }
1 Like

thanks - that did the trick. appreciated!

@seant_unity I’ve tried this on a ControlTrack to get the GameObject or the PlayableDirector that the ControlTrack is controlling, but it returns null.

TimelineAsset timelineAsset = director.playableAsset as TimelineAsset;

foreach (var track in timelineAsset.GetOutputTracks())
{
   if (track is ControlTrack)
   {
     GameObject obj = director.GetGenericBinding(track) as GameObject ;
     Debug.Log("Object name: " + obj.name);
     PlayableDirector controlledDirector = director.GetGenericBinding(track) as PlayableDirector;
     Debug.Log("Director name: " + controlledDirector.name);
   }
}

I’ve tried both of these, but all I get is “NullReferenceException: Object reference not set to an instance of an object”.

Is this the correct/intended way to do it for ControlTracks?

TimelineAsset timelineAsset = director.playableAsset as TimelineAsset;

foreach (var track in timelineAsset.GetOutputTracks())
{
    if (track is ControlTrack)
    {
        foreach (TimelineClip clip in track.GetClips())
        {
            ControlPlayableAsset controlPlayableAsset = (ControlPlayableAsset)clip.asset;
            PropertyName propertyName = controlPlayableAsset.sourceGameObject.exposedName;

            bool idValid = false; 
            Object obj = director.GetReferenceValue(propertyName, out idValid);
            if (idValid)
               Debug.Log("Object name: " + obj.name);
        }
    }
}

Instead of doing it for each type, you can also simply assign the binding as a “Behaviour” object to be able to have access to its transform. removes the need to check every type.

        public static Transform GetTransformBinding(PlayableDirector director, TrackAsset track)
        {
            if (director == null)
                return null;

            var binding = director.GetGenericBinding(track) as Behaviour;
            return binding.transform;
        }