Search Unity

  1. We are migrating the Unity Forums to Unity Discussions by the end of July. Read our announcement for more information and let us know if you have any questions.
    Dismiss Notice
  2. Dismiss Notice

Question How can I find the top most root playable?

Discussion in 'Timeline' started by CDF, Feb 14, 2024.

  1. CDF

    CDF

    Joined:
    Sep 14, 2013
    Posts:
    1,324
    I have a nested timeline and a custom playable on that timeline.
    This custom playable needs to pause the top level timeline for some period of time.

    It doesn't appear like I can get this top most root playable.
    This method:

    playable.GetGraph().GetRootPlayable(0);


    Is only returning the graph controlling the sub timeline.

    How can I access the graph that is controlling the sub timeline?
     
  2. CDF

    CDF

    Joined:
    Sep 14, 2013
    Posts:
    1,324
    I could be wrong, but I think this isn't possible as there's no connection between the incoming graph from "DirectorControlPlayable" and the director assigned to the control track that creates its own graph.

    directorEval.png

    The director assigned to the control track creates its own internal graph that is disconnected from the root playable graph.

    And I don't see how anything under directors graph can now access that root graph. :(
     
    Yuchen_Chang likes this.
  3. Yuchen_Chang

    Yuchen_Chang

    Joined:
    Apr 24, 2020
    Posts:
    137
    Since the director field is marked as public, you can loop through your parent's root playable's descendants and find the DirectorControlPlayable, and hence you can access the child playable graph through the director.
    (better use PlayableGraph Visualizer to check the structure for Control Track, to locate where DirectorControlPlayable would be)
     
  4. CDF

    CDF

    Joined:
    Sep 14, 2013
    Posts:
    1,324
    Sorry, not following. I want the ancestors not descendants.

    I have the visualizer, and there's no link between the playableGraph the controlTrack creates and the timeline containing the control track. I was expecting this result:

    RootTimeline
    --- PlayableGraph
    ------ ControlTrack
    --------- MyPlayableBehaviour

    But it's actually this:

    RootTimeline
    --- PlayableGraph
    ------ ControlTrack

    PlayableGraph (From Control Track's director)
    --- MyPlayableBehaviour

    From "MyPlayableBehaviour" I'm unable to find "RootTimeline" anymore. Which makes it impossible to control the playhead of that timeline from my behaviour.
     
    Yuchen_Chang likes this.
  5. Yuchen_Chang

    Yuchen_Chang

    Joined:
    Apr 24, 2020
    Posts:
    137
    Oh, sorry, I didn't read carefully. It indeed is much harder...
    If I was in the same situation, I would create another controller script that assists PlayableDirector. For example, parent controller injects itself into the child controller before playing, and when child controller receives some event from child PlayableDirector (through marker, etc), child controller execute some method of parent controller.
     
  6. CDF

    CDF

    Joined:
    Sep 14, 2013
    Posts:
    1,324
    Thanks for the help. I had to go with something different.

    These sub timelines I'm creating are used in multiple different root timelines.
    So I can't really make an assumption about what root timeline I need to send events to from the behaviour.

    So I went with a completely custom track that creates playables from direct references to timeline assets.
    There I can link the playables up following the graph chain.

    My sub timelines don't need to handle animation or anything fancy. They just contain these playable behaviours that can modify the root timeline's time and speed.

    The workflow isn't great, but it does the job.
    It's pretty simple too:
    Code (CSharp):
    1. [TrackClipType(typeof(TimelinePlayableAsset), false)]
    2. [TrackBindingType(typeof(GameObject), TrackBindingFlags.None)]
    3. public class TimelineAssetTrack : PlayableTrack {
    4. }
    5.  
    6. public class TimelinePlayableAsset : PlayableAsset, ITimelineClipAsset {
    7.  
    8.     public ClipCaps clipCaps => ClipCaps.None;
    9.  
    10.     public override double duration => asset != null ? asset.duration : base.duration;
    11.  
    12.     public TimelineAsset TimelineAsset => asset;
    13.  
    14.     [SerializeField] public TimelineAsset asset;
    15.     [SerializeField] public PlayableTraversalMode traversalMode = PlayableTraversalMode.Mix;
    16.  
    17.     public override Playable CreatePlayable(PlayableGraph graph, GameObject owner) {
    18.  
    19.         if (asset == null) {
    20.             return Playable.Create(graph);
    21.         }
    22.  
    23.         Playable playable = asset.CreatePlayable(graph, owner);
    24.         playable.SetTraversalMode(traversalMode);
    25.  
    26.         return playable;
    27.     }
    28. }
     
    Yuchen_Chang likes this.