Hi i want to set the played frame - the "time" of the timeline manually - as far i can control the slider in the timeline by using this code but the frame doesnt update correctly timeline update method gametime, play on awake is false hope you can help me Code (CSharp): public void setTime() { // gets called by my scrollbar Scrollbar Scrollbar = scroll.GetComponent<Scrollbar>(); PlayableDirector playableDirector = GetComponent<PlayableDirector>(); float maxtime = 1; playableDirector.time = Scrollbar.value * maxtime; }
thank you for the answer: for other readers - my final solution was Code (CSharp): private void setTime() { Scrollbar Scrollbar = scroll.GetComponent<Scrollbar>(); PlayableDirector playableDirector = GetComponent<PlayableDirector>(); Debug.Log(Scrollbar.value); float maxtime = 1; actTime = Scrollbar.value * maxtime; playableDirector.time = actTime; playableDirector.RebuildGraph(); playableDirector.Play(); playableDirector.playableGraph.GetRootPlayable(0).SetSpeed(0); } i had to rebuild the graph because otherwise playableGraph.GetRootPlayable(0) finds no graph - maybe i didnt understand the concept but actually there is a timeline graph in the scene already - nevertheless by setting the speed to 0 and resetting the time i was able to control the time of a timeline manually
Hi @seant_unity sorry for the necro, just wanted to thank you for this additional note. I'm using a similar approach where I have the player "scrob" through a Timeline animation. I've been looking to solve a problem where Signal Emitters would fire off multiple times when set to fire retroactively. The addition of a playableDirector.playableGraph.IsValid() is false check made the difference, and spares me having to roll my own custom Signal Emitters, phew! Cheers. (Edit: turns out I now need to figure out a way of triggering Signal Emitters when moving backwards through the timeline though, as it seems that I was relying on the events continuously firing, to restore certain scene elements to a previous state...)
That will work, but you should only rebuild the graph and start playing if playableDirector.playState == PlayState.Paused. Otherwise each time you call this method, you will reconstruct the entire timeline instance, which can be very costly.
Code (CSharp): private void setTime() { Scrollbar Scrollbar = scroll.GetComponent<Scrollbar>(); PlayableDirector playableDirector = GetComponent<PlayableDirector>(); Debug.Log(Scrollbar.value); float maxtime = 1; actTime = Scrollbar.value * maxtime; if (playableDirector.state == PlayState.Paused) { // this will call RebuildGraph if needed playableDirector.Play(); // will set the speed of the graph to 0, so it's always playing but never // advancing playableDirector.playableGraph.GetRootPlayable(0).SetSpeed(0); } playableDirector.time = actTime; }
I don't know if this is better or not, but I hooked up the slider directly to the setTime function and it worked well. Code (CSharp): public PlayableDirector m_playable; public void setTime(Vector2 value) { //Invert slider value float t = Mathf.Lerp(1, 0, value.y); double maxtime = m_playable.duration; double actTime = t * maxtime; if (m_playable.state == PlayState.Paused) { // this will call RebuildGraph if needed m_playable.Play(); // will set the speed of the graph to 0, so it's always playing but never // advancing m_playable.playableGraph.GetRootPlayable(0).SetSpeed(0); } if (actTime < 0) actTime = 0; if (actTime > maxtime) actTime = maxtime; m_playable.time = actTime; }