停止中でもTimelineでDOTweenを再生させる

 TimelineとDOTweenを組み合わせて、出現と消失の演出をクリップ1個で再生出来るようにしたい。ということでControl TrackとDOTweenの仕様から落としどころを探ってみたところ以下のようになりました。

  • クリップの始点で出現演出開始、終点で消失演出開始
  • DOTweenのパラメータはInspectorから動的に変更が可能
  • 停止中は出現演出のみ。消失演出はカットされてノーウェイトで消える

f:id:ichika292:20171115164023g:plain
 Timelineのお陰でステートレスに色々作れて楽しいですね。

実装

using UnityEngine;
using UnityEngine.Timeline;
using DG.Tweening;

public class TimeControllTest : MonoBehaviour, ITimeControl
{
    Sequence sequence;
    
    void Init()
    {
        gameObject.SetActive(false);
        transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
        transform.localScale = Vector3.up;
    }

    void ITimeControl.OnControlTimeStart()
    {
        gameObject.SetActive(true);
        sequence.Kill();
        sequence = DOTween.Sequence()
            .Append(transform.DOScale(1f, 1f).SetEase(Ease.OutBounce))
            .Join(transform.DORotate(Vector3.up * 360f, 1f, RotateMode.FastBeyond360))
            .SetRecyclable()
            .Play();
    }

    void ITimeControl.OnControlTimeStop()
    {
        sequence.Kill();
        sequence = DOTween.Sequence()
            .Append(transform.DOScale(Vector3.up, 1f).SetEase(Ease.OutExpo))
            .Join(transform.DORotate(Vector3.up * 360f, 1f, RotateMode.FastBeyond360))
            .AppendCallback(Init)
            .SetRecyclable()
            .Play();

#if UNITY_EDITOR
        if (Application.isPlaying == false)
            sequence.Complete(true);
#endif
    }

    void ITimeControl.SetTime(double time)
    {
#if UNITY_EDITOR
        if(Application.isPlaying == false)
            sequence.Goto((float)time);
#endif
    }
}

 このコードはUnity2017.2.0p1で作成しました。

解説

 上記のコードをアタッチしたGameObjectをControlPlayableAssetにセットして使います。クリップの終点と消失演出の完了で位置が違うので、Control Activationのチェックを外しておきます。
f:id:ichika292:20171114134854p:plain

停止中の出現演出

    void ITimeControl.SetTime(double time)
    {
#if UNITY_EDITOR
        if(Application.isPlaying == false)
            sequence.Goto((float)time);
#endif
    }

 SetTimeはクリップ部分を移動する度に呼び出されます。消失演出はクリップ外になるのでPreviewでの再生は断念しました。

停止中の消失演出

    void ITimeControl.OnControlTimeStop()
    {
...
            .AppendCallback(Init)
            .SetRecyclable()
            .Play();
        
#if UNITY_EDITOR
        if (Application.isPlaying == false)
            sequence.Complete(true);
#endif
    }

 OnControlTimeStopはTrack部分から出た時に呼び出されます。
 停止中はDOTweenのPlay()では再生されない為、Complete()で過程を飛ばして最終的な状態を呼び出しています。Completeの引数はbool withCallbacksで、trueにしなければSequenceのAppendCallback(Init)が実行されません。
 動的にTweenを変更する場合を考慮して毎回Killしているので、効果の程はよく分からぬままにSetRecyclabeを呼んでいます。もっとスマートなやり方あるかも...。