Search Unity

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

Discussion in 'Timeline' started by metaphysician, May 13, 2020.

  1. metaphysician

    metaphysician

    Joined:
    May 29, 2012
    Posts:
    190
    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.

    Code (CSharp):
    1.        
    2. for (int trackCount=0; trackCount < currList.Length; trackCount++)
    3.         {
    4.             //set bound GameObject to each associated GameObject in track
    5.             TrackAsset trackAsset = timeline.GetOutputTrack(trackCount);
    6.  
    7.             //this is what i don't know
    8.             GameObject boundGameObj = trackAsset.outputs.sourceObject.GameObject ?
    9.  
    10.             currList[trackCount].m_boundGameObject = boundGameObj;
    11.         }
    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
     
  2. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    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...
     
  3. metaphysician

    metaphysician

    Joined:
    May 29, 2012
    Posts:
    190
    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!
     
  4. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    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.

    Code (CSharp):
    1.         public static Transform GetTransformBinding(PlayableDirector director, TrackAsset track)
    2.         {
    3.             if (director == null)
    4.                 return null;
    5.  
    6.             var binding = director.GetGenericBinding(track);
    7.             if (binding is Component)
    8.                 return ((Component) binding).transform;
    9.  
    10.             if (binding is GameObject)
    11.                 return ((GameObject) binding).transform;
    12.  
    13.             return null;
    14.         }
    15.  
     
    zeimhall likes this.
  5. metaphysician

    metaphysician

    Joined:
    May 29, 2012
    Posts:
    190
    thanks - that did the trick. appreciated!
     
  6. KristofferH

    KristofferH

    Joined:
    Oct 27, 2012
    Posts:
    52
    @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.
    Code (CSharp):
    1. TimelineAsset timelineAsset = director.playableAsset as TimelineAsset;
    2.  
    3. foreach (var track in timelineAsset.GetOutputTracks())
    4. {
    5.    if (track is ControlTrack)
    6.    {
    7.      GameObject obj = director.GetGenericBinding(track) as GameObject ;
    8.      Debug.Log("Object name: " + obj.name);
    9.      PlayableDirector controlledDirector = director.GetGenericBinding(track) as PlayableDirector;
    10.      Debug.Log("Director name: " + controlledDirector.name);
    11.    }
    12. }
    I've tried both of these, but all I get is "NullReferenceException: Object reference not set to an instance of an object".
     
  7. KristofferH

    KristofferH

    Joined:
    Oct 27, 2012
    Posts:
    52
    Is this the correct/intended way to do it for ControlTracks?

    Code (CSharp):
    1. TimelineAsset timelineAsset = director.playableAsset as TimelineAsset;
    2.  
    3. foreach (var track in timelineAsset.GetOutputTracks())
    4. {
    5.     if (track is ControlTrack)
    6.     {
    7.         foreach (TimelineClip clip in track.GetClips())
    8.         {
    9.             ControlPlayableAsset controlPlayableAsset = (ControlPlayableAsset)clip.asset;
    10.             PropertyName propertyName = controlPlayableAsset.sourceGameObject.exposedName;
    11.  
    12.             bool idValid = false;
    13.             Object obj = director.GetReferenceValue(propertyName, out idValid);
    14.             if (idValid)
    15.                Debug.Log("Object name: " + obj.name);
    16.         }
    17.     }
    18. }
     
    Last edited: Sep 13, 2021
  8. UbiRose

    UbiRose

    Joined:
    Dec 10, 2021
    Posts:
    2
    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.
    Code (CSharp):
    1.         public static Transform GetTransformBinding(PlayableDirector director, TrackAsset track)
    2.         {
    3.             if (director == null)
    4.                 return null;
    5.  
    6.             var binding = director.GetGenericBinding(track) as Behaviour;
    7.             return binding.transform;
    8.         }