How can I find the top most root playable?

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?

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.

9642671--1371212--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. :frowning:

1 Like

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)

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.

1 Like

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.

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:

[TrackClipType(typeof(TimelinePlayableAsset), false)]
[TrackBindingType(typeof(GameObject), TrackBindingFlags.None)]
public class TimelineAssetTrack : PlayableTrack {
}

public class TimelinePlayableAsset : PlayableAsset, ITimelineClipAsset {

    public ClipCaps clipCaps => ClipCaps.None;

    public override double duration => asset != null ? asset.duration : base.duration;

    public TimelineAsset TimelineAsset => asset;

    [SerializeField] public TimelineAsset asset;
    [SerializeField] public PlayableTraversalMode traversalMode = PlayableTraversalMode.Mix;

    public override Playable CreatePlayable(PlayableGraph graph, GameObject owner) {

        if (asset == null) {
            return Playable.Create(graph);
        }

        Playable playable = asset.CreatePlayable(graph, owner);
        playable.SetTraversalMode(traversalMode);

        return playable;
    }
}
1 Like