こんにちはっ🌟八ツ橋まろんですっ!
ARアプリを作っているときに、Timelineをスライダーで操作したくなったのでスクリプトを書きました。本記事ではそのコードと解説をします。
↓↓↓↓このコードによってこんなことができます↓↓↓↓(GIF)
(このGIFではアニメーションだけが入ったTimelineを使用しています)
・再生ボタン/一時停止ボタンの実装
・Timelineの進行度合いがスライダーに反映される
・スライダーの位置をクリックして変えるとTimelineの再生位置も連動する
以下、完成コード
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Playables;
using System; // Actionに必要
public class TimelineUiController : MonoBehaviour
{
[SerializeField]
PlayableDirector timeline;
[SerializeField]
Slider slider;
[SerializeField]
GameObject playButton;
[SerializeField]
GameObject pauseButton;
double length;
float sliderValue;
float sliderValueStored;
float time;
private void Start()
{
length = timeline.duration;
Play();
}
void Update()
{
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);
}
else if(time != sliderValueStored)
{
slider.value = time;
sliderValueStored = time;
}
}
public void Play()
{
timeline.Play();
playButton.SetActive(false);
pauseButton.SetActive(true);
}
public void Stop()
{
timeline.Stop();
PlayOneFrame();
}
public void Pause()
{
timeline.Pause();
time = ConvertDtoF(timeline.time);
sliderValue = time;
sliderValueStored = time;
playButton.SetActive(true);
pauseButton.SetActive(false);
}
public void LengthReset()
{
length = timeline.duration;
}
void PlayOneFrame()
{
Play();
//1フレーム後にPauseする
StartCoroutine(DelayMethod(1, () => {Pause(); }));
}
private IEnumerator DelayMethod(int delayFrameCount, Action action)
{
for (var i = 0; i < delayFrameCount; i++)
{
yield return null;
}
action();
}
void SetTimelineTime(float f)
{
double d = ConvertFtoD(f);
timeline.time = d;
PlayOneFrame();
}
double ConvertFtoD(float f)
{
double d = (double)(f * length);
return d;
}
float ConvertDtoF(double d)
{
float f = (float)d / (float)length;
return f;
}
}
###使い方
[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制御を越えてカメラワークやエフェクトの巻き戻しとかを任意でやりたい場合に使えます✨よかったら使ってみてください。
八ツ橋まろん