Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. 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:
    1,516
    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:
    1,516
    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. }
     
    Shrubokrant likes this.
  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:
    1,516
    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:
    1,516
    Right -- msl_manni is absolutely correct.
     
  9. CnrGames

    CnrGames

    Joined:
    Jul 28, 2016
    Posts:
    1
    HI, can someone help me please?
    How can i take all my Playable Director'binding objects to a list,i want to create a list that contains all binding objects from my current Playable Director.

    And i dont know how to right it,so can you make a small script as example for me to catch he ideia please.
     
    tonytopper likes this.
  10. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    There isn't an API call to do it, but you can use the serialized properties to discover the internal list.

    Code (CSharp):
    1.     public static void DisplayBindings(PlayableDirector director)
    2.     {
    3.         var obj = new SerializedObject(director);
    4.         var bindings = obj.FindProperty("m_SceneBindings");
    5.         for (int i = 0; i < bindings.arraySize; i++)
    6.         {
    7.             var binding = bindings.GetArrayElementAtIndex(i);
    8.             var trackProp = binding.FindPropertyRelative("key");
    9.             var sceneObjProp = binding.FindPropertyRelative("value");
    10.             var track = trackProp.objectReferenceValue;
    11.             var sceneObj = sceneObjProp.objectReferenceValue;
    12.  
    13.             Debug.LogFormat("Binding {0} {1}", track != null ? track.name : "Null", sceneObj != null ? sceneObj.name : "Null");
    14.         }
    15.     }
    16.  
     
  11. xyvan

    xyvan

    Joined:
    Jun 21, 2014
    Posts:
    13
    Is it possible to get to the gameobject of the sceneObjProp

    i would like to deactive the current blinded object in a timeline
     
    Last edited: Mar 31, 2019
  12. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    PlayableDirector.GetReferenceValue() will retrieve the gameObject. You need the key value, which is the exposedName field of the ExposedReference on your clip.

    e.g. something like

    bool isValid = false;
    var exposedName = ((ControlPlayableAsset) clip.asset).sourceGameObject.exposedName;
    var binding = director.GetReferenceValue(exposedName, out isValid);
     
  13. insominx

    insominx

    Joined:
    Jan 23, 2012
    Posts:
    32
    I had to do something similar - in my case swapping out the brain used in any timeline track of a child. It's my first brain surgery :D
    Code (CSharp):
    1.     void TransplantBrain(PlayableDirector director, CinemachineBrain newBrain) {
    2.       var outputs = director.playableAsset.outputs;
    3.       foreach (var output in outputs) {
    4.         if (output.outputTargetType == typeof(CinemachineBrain)) {
    5.           director.ClearGenericBinding(output.sourceObject);
    6.           director.SetGenericBinding(output.sourceObject, newBrain);
    7.         }
    8.       }
    9.     }
    10.  
    I should also mention that in order for this to work I had to "jiggle the handle" by disabling and re-enabling the brain.

    Code (CSharp):
    1.         var directorList = page.GetComponentsInChildren<PlayableDirector>();
    2.         newBrain.enabled = false;
    3.         foreach (var director in directorList) {
    4.           TransplantBrain(director, newBrain);
    5.         }
    6.         newBrain.enabled = true;
    7.       }
    8.  
     
    sanity90210, Curipoc and ferretnt like this.
  14. tonytopper

    tonytopper

    Joined:
    Jun 25, 2018
    Posts:
    194
    Even the simple task of setting up multiple PlayableDirector bindings on a prefab and then switching between them with a script as needed feels obtuse. I just want to switch the Playable here between the different bindings already on the director.

    I can see the bindings and the playable assets right there in the Editor, but I can't figure out how to navigate these APIs to get to them.
     

    Attached Files:

    Brightori, DRRosen3 and Genebris like this.
  15. tonytopper

    tonytopper

    Joined:
    Jun 25, 2018
    Posts:
    194
    Has this API matured at all? It still looks too low-level glancing at the API docs.

    As a footnote, my game's development could easily be 2x more productive if Unity's APIs were more mature and developer friendly. It doesn't appear Unity is putting enough effort into this. As someone who put aside a lucrative Silicon Valley tech leadership career to pursue my dream of making a video game, this is literally costing me 100s of thousands of dollars.
     
    andreyefimov2010 likes this.