Search Unity

  1. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  4. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Set PlayableDirector bindings from script

Discussion in 'Timeline' started by Despin, Aug 9, 2017.

  1. Despin

    Despin

    Joined:
    Oct 2, 2014
    Posts:
    3
    Hi guys.

    I have a lot of custom Playables and all of it have a same TrackBindingType (MyType, for example).

    Code (CSharp):
    1.  
    2. [TrackClipType(typeof(ClipType1))]
    3. [TrackBindingType(typeof(MyType))]
    4. public class Type1Track : TrackAsset
    5. {
    6.     //Some code here
    7. }
    e.t.c.

    Idea is, load a timeline asset from resources set it to GO Director and instantiate all of Director bindings with the same component typeof MyType form this GO.

    I understang how to do it manually, but manually setting ruin all the conception. I wonder it must be something like that:

    Code (CSharp):
    1.  
    2.     void Start()
    3.     {
    4.         PlayableDirector director = this.GetComponent<PlayableDirector>();
    5.         director.playableAsset = this.TimelineAsset;
    6.         //Set bindings here
    7.         director.SOME_BIND_METHOD(GetComponent<MyType>());
    8.  
    9.         director.Play();
    10.     }
    Any suggestions. Thanks.
     
  2. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    521
    The method you are looking for is PlayableDirector.SetGenericBinding.

    The first parameter is a reference to the track, which you can either from iterating through the timeline assets, or it's also the sourceObject field of the PlayableBinding struct returned from PlayableAsset.outputs.

    The second parameter is the component you want to bind to the track.
     
  3. Despin

    Despin

    Joined:
    Oct 2, 2014
    Posts:
    3
    Thanks for answer. Another question.
    Is there any method to get this binded object inside of PlayableBehaviour exept void ProcessFrame(Playable playable, FrameData info, object playerData) method?
    For exmple I need access to "object playerData" (my binded object) variable at the start of playable track plays or at the start of Graph Plays. Methods OnBehaviourPlay and OnGraphStart dont have an "object playerData" argument.
     
  4. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    521
    No, but there are a couple of workarounds.

    If you are using a Mixer Playable for the track, ProcessFrame runs every frame. You can grab it on the first frame that's called and pass it to it's inputs if you need it on clip playables.

    Or you pass it down from the track... something like

    Code (CSharp):
    1. public class MyPlayableAsset
    2. {
    3.     public Object binding { get; set; }
    4.     ....
    5.    
    6.     public override Playable CreatePlayable(PlayableGraph graph, GameObject go)
    7.     {
    8.             // pass the binding to the playable instance
    9.             var handle = ScriptPlayable<ParticleControlPlayable>.Create(graph, template);
    10.             handle.GetBehaviour().binding = binding;
    11.             return handle;
    12.     }
    13.    
    14. }
    15.  
    16. public class MyTrack : TrackAsset
    17. {
    18.      ...
    19.         public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
    20.         {
    21.               // before building, update the binding field in the clips assets;
    22.               var director = go.GetComponent<PlayableDirector>();
    23.               var binding = director.GetGenericBinding(this);
    24.              
    25.               foreach (var c in GetClips())
    26.               {
    27.                     var myAsset = c.asset as MyPlayableAsset;
    28.                     if (myAsset != null)
    29.                         myAsset.binding = binding;            
    30.               }
    31.    
    32.               return base.CreateTrackMixer(graph, go, inputCount);
    33.         }
    34.  
    35. }
     
  5. Despin

    Despin

    Joined:
    Oct 2, 2014
    Posts:
    3
    Thanks, this code work fine. One more thing.

    I try change playable speed at runtime like this:
    Code (CSharp):
    1.  
    2.             PlayableDirector director = this.GetComponent<PlayableDirector>();
    3.             for (int i = 0; i < director.playableGraph.GetOutputCount(); i++)
    4.             {
    5.                 director.playableGraph.GetOutput(i).GetSourcePlayable().SetSpeed(0.1F);
    6.             }
    7.             director.Play();
    But its throw a "InvalidOperationException: This PlayableGraph is invalid. To create a valid PlayableGraph, please use the CreateGraph method." exception.

    Is there any method to change playable speed at runtime?
     
  6. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    521
    That will do it, but the playablegraph isn't valid until after director.Play() is called.
     
  7. msl_manni

    msl_manni

    Joined:
    Jul 5, 2011
    Posts:
    272
    I suppose that you can not set speed of individual tracks of timeline, but you should set speed of the director itself. The whole timeline playable tracks are controlled via rootplayable graph so you should try the following code.

    Code (CSharp):
    1. director.playableGraph.GetRootPlayable().SetSpeed();
     
  8. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    521
    Right -- msl_manni is absolutely correct.