こんにちはっ🌟八ツ橋まろんですっ!
ARアプリを作っているときに、Timelineをスライダーで操作したくなったのでスクリプトを書きました。本記事ではそのコードと解説をします。
↓↓↓↓このコードによってこんなことができます↓↓↓↓(GIF)
(このGIFではアニメーションだけが入ったTimelineを使用しています)
・再生ボタン/一時停止ボタンの実装
・Timelineの進行度合いがスライダーに反映される
・スライダーの位置をクリックして変えるとTimelineの再生位置も連動する
以下、完成コード
TimelineUiController.cs
usingSystem.Collections;usingUnityEngine;usingUnityEngine.UI;usingUnityEngine.Playables;usingSystem;// Actionに必要publicclassTimelineUiController:MonoBehaviour{[SerializeField]PlayableDirectortimeline;[SerializeField]Sliderslider;[SerializeField]GameObjectplayButton;[SerializeField]GameObjectpauseButton;doublelength;floatsliderValue;floatsliderValueStored;floattime;privatevoidStart(){length=timeline.duration;Play();}voidUpdate(){sliderValue=slider.value;time=ConvertDtoF(timeline.time);if(time>=0.995&&timeline.extrapolationMode!=DirectorWrapMode.Loop){playButton.SetActive(true);pauseButton.SetActive(false);}if(sliderValue!=sliderValueStored){sliderValueStored=sliderValue;time=sliderValue;SetTimelineTime(time);}elseif(time!=sliderValueStored){slider.value=time;sliderValueStored=time;}}publicvoidPlay(){timeline.Play();playButton.SetActive(false);pauseButton.SetActive(true);}publicvoidStop(){timeline.Stop();PlayOneFrame();}publicvoidPause(){timeline.Pause();time=ConvertDtoF(timeline.time);sliderValue=time;sliderValueStored=time;playButton.SetActive(true);pauseButton.SetActive(false);}publicvoidLengthReset(){length=timeline.duration;}voidPlayOneFrame(){Play();//1フレーム後にPauseするStartCoroutine(DelayMethod(1,()=>{Pause();}));}privateIEnumeratorDelayMethod(intdelayFrameCount,Actionaction){for(vari=0;i<delayFrameCount;i++){yieldreturnnull;}action();}voidSetTimelineTime(floatf){doubled=ConvertFtoD(f);timeline.time=d;PlayOneFrame();}doubleConvertFtoD(floatf){doubled=(double)(f*length);returnd;}floatConvertDtoF(doubled){floatf=(float)d/(float)length;returnf;}}
使い方
[SerializeField]
PlayableDirector timeline;
[SerializeField]
Slider slider;
[SerializeField]
GameObject playButton;
[SerializeField]
GameObject pauseButton;
上記にPlayableDirectorとスライダー、再生ボタン、停止ボタンをあてがってください。
解説
Timelineの総時間は
length = timeline.duration;
で取得できます。ただし、これはdouble型で得られるため、float型に変換しないといけないので注意。
float ConvertDtoF(double d)
{
float f = (float)d / (float)length;
return f;
}
timeline.timeで現在の再生位置をdouble型で取得し、総時間で割ったあとにfloat型に変換して、0~1にしています。
time = ConvertDtoF(timeline.time);
スライダーを触ってtimelineの再生位置を変更する場合、timeline.Pause();してtimeline.time = xxx;だけではスライダー位置が動かないため、その後に1フレームだけ再生することでスライダー位置を動かすようにしています。
おわりに
Timelineの再生位置制御の需要は、なかなかないと思いますが、Animation制御を越えてカメラワークやエフェクトの巻き戻しとかを任意でやりたい場合に使えます✨よかったら使ってみてください。
八ツ橋まろん