こんにちは「DOTweenの教科書」執筆者のオオバです。

お悩みさん
お悩みさん
  • DOTweenの巻き戻し(逆再生)のやり方がわからない
  • DOTweenで早送りすることできる?
  • オオバ
    オオバ
    本記事ではこれらの悩みを解決します。

    アニメーションで「巻き戻し(逆再生)」や「早送り」の要望は時々発生しますよね。
    エンジニアは悩みます。

    「どうやったら実装できるだろうか」

    オススメしたいのは DOTween
    DOTweenを使うとかなり シンプルに実装 できます。

    そして本記事では Animatorと連動 したアニメーションを要件に追加します。

    【DOTween】巻き戻し(逆再生)と早送りする方法_0

    つまりこういうことです。
    DOTween、Animator(Unityちゃんのアニメーション)ともに
    巻き戻し(逆再生)、早送りを実装してみようという話。

    巻き戻し(逆再生)と早送りに困っている人は、ぜひ最後まで読んでみてください。

    DOTweenとAnimatorの「巻き戻し(逆再生)」「早送り」は分離して実装

    はじめに結論を簡単にまとめます。

    DOTweenとAnimatorの巻き戻し(逆再生)、早送りは分離して実装

    ①DOTweenの巻き戻しは2通りのやり方で実装可能

    ②DOTweenの早送りはTweenのtimeScaleで変更可能

    ③AnimatorはAnimationStateのSpeedで対応

    DOTweenとAnimatorは別々で実装したほうがよいです。お互い全く実装が異なります。

    ただ、DOTweenとAnimatorは連携することが多いです。この記事を通してDOTweenとAnimatorの連携方法を学び、表現の幅を増やしてみましょう。

    では詳しい解説に入ります。

    →11万文字で徹底解説した「DOTweenの教科書」Unityアニメーションの超効率化ツールはこちら

    DOTweenの巻き戻しには2通りの方法がある

    まずはDOTweenの巻き戻しから実装していきましょう。DOTweenの巻き戻しは2通りの方法があります。1つは PlayBackwards メソッドを呼ぶ。2つ目は timeScale-1 を代入する方法です。

    今回は1つ目の PlayBackwords メソッドを使って紹介します。早速ソースコードを紹介。

    [SerializeField] Transform _unityChan;  
    
    IEnumerator Start()  
    {
        var tween = _unityChan.DOLocalMoveX(-2f, 3f).SetEase(Ease.Linear);  
        yield return new WaitForSeconds(2);  
        // 2秒経過で巻き戻し実行  
        tween.PlayBackwards();  
    }
    

    Unityちゃんが走り出して、2秒後に巻き戻る(逆生する)サンプルです。

    【DOTween】巻き戻し(逆再生)と早送りする方法_1

    Animatorは何も処理を加えていないため、そのまま再生されていますが、
    Unityちゃんの移動自体は逆再生しています。

    DOTweenの PlayBackwards メソッドを使うと簡単に巻き戻すことができるのです。

    DOTweenの早送りはtimeScaleを変更する

    次は早送りです。Tweenインスタンスの timeScale を使うと簡単です。TweenインスタンスとはDOTweenを実行した戻り値です。

    例えば DOLocalMove を実行した戻り値はTween型。つまりDOTweenを実行した後もTweenインスタンス経由でいろんな処理を挟むことができるのです。

    今回はDOTween再生後の 任意のタイミングで早送り するという話。

    サンプルコードはこちらです。

    [SerializeField] Transform _unityChan;  
    
    IEnumerator Start()  
    {
        // Tweenインスタンス取得  
        var tween = _unityChan.DOLocalMoveX(10f, 3f).SetEase(Ease.Linear);  
        yield return new WaitForSeconds(1f);  
        // 1秒後に2倍のスピードへ  
        tween.timeScale = 2f;  
    }
    

    1秒後に2倍のスピードに変更します。

    【DOTween】巻き戻し(逆再生)と早送りする方法_2

    このコードを適用するとこんな感じになります。

    まだAnimatorの方は何も処理を追加していないため、あくまで UnityちゃんのX座標が早く動いただけ の状態です。

    DOTweenの巻き戻し(逆再生)、早送りの実装は以上です。思った以上に簡単でしたよね。

    これからAnimator側の処理に入ります。

    Animatorの巻き戻し(逆再生)する方法

    Animatorの巻き戻し(逆再生)は少し面倒くさいです。以前のUnityではシンプルでした。Animatorインスタンスのspeedプロパティに-1を代入するだけでしたが Unityのバージョンアップで廃止

    現在は AnimationStateSpeedを変更 することで対応できます。

    Animatorの巻き戻し(逆再生)準備

    AnimtorControllerに巻き戻し(逆再生)の準備をしていきます。

    【DOTween】巻き戻し(逆再生)と早送りする方法_3

    SD版Unityちゃんをそのまま使っているなら、SD_unitychan_humanoid または、 SD_unitychan_generic を選択します。

    AnimatorWindowを開きましょう。

    【DOTween】巻き戻し(逆再生)と早送りする方法_4

    メニューWindow > Animation > Animator をクリック

    【DOTween】巻き戻し(逆再生)と早送りする方法_5

    【DOTween】巻き戻し(逆再生)と早送りする方法_6

    Float型のパラメータが追加されるので、今回は Speed と命名しデフォルト値として 1 をセットしておきます。

    【DOTween】巻き戻し(逆再生)と早送りする方法_8

    Animatorウィンドウ内のアニメーションステートを選択します。
    今回は走るアニメーションを使っているので Running@loop を選択。

    インスペクタを確認します。

    【DOTween】巻き戻し(逆再生)と早送りする方法_9

    これで準備は完了です。

    SetFloatでAnimatorの巻き戻し(逆再生)の実装

    つまり、このSpeedというパラメータに1を入れると通常再生、「-1」をセットすると逆再生するということです。

    ではDOTweenとセットで再生させてみます。

    【DOTween】巻き戻し(逆再生)と早送りする方法_10

    サンプルコードはこちらです。

    [SerializeField] Transform _unityChan;  
    [SerializeField] Animator _animator;  
    
    IEnumerator Start()  
    {
        var tween = _unityChan.DOLocalMoveX(10f, 3f).SetEase(Ease.Linear);  
        yield return new WaitForSeconds(2);  
        // 2秒経過で巻き戻し実行  
        tween.PlayBackwards();  
        // Animatorを巻き戻し再生  
        _animator.SetFloat(-1f);  
    }
    

    ポイントは Animatorに対して SetFloat メソッドで -1を渡している所。この値が先ほど設定した AnimationStateのSpeed値に乗算 されて、逆再生アニメーションになるのです。

    これでAnimatorの巻き戻し(逆再生)ができました!!

    Animatorの早送り

    Animatorの早送りは前述の 「Animatorの巻き戻し(逆再生)」 の応用です。AnimationStateに1より大きな値を代入すればよいのです。

    サンプルコードから紹介します。

    [SerializeField] Animator _animator;  
    
    IEnumerator Start()  
    {
        yield return new WaitForSeconds(2);  
        // 2秒経過で早送り実行(3倍のスピードへ)  
        _animator.SetFloat(3f);  
    }
    

    👇実行するとこのような感じに再生されます。

    【DOTween】巻き戻し(逆再生)と早送りする方法_11

    今回はわかりやすくするため3倍のスピードにしています。Animatorに対して SetFloat メソッドでパラメータを渡すだけなのでとても簡単です。

    これでAnimatorの早送りは実装完了です。

    【完成】DOTweenとAnimatorの巻き戻し(逆再生)と早送り

    では最後にDOTween、Animator両方の巻き戻し(逆再生)、早送りすべて込み込みで再生してみます。

    【DOTween】巻き戻し(逆再生)と早送りする方法_12

    完成!!

    サンプルコードはこちらです。

    IEnumerator Start()  
    {
        tween = unityChan.DOLocalMoveX(2f, 3f).SetEase(Ease.Linear);  
        yield return new WaitForSeconds(2f);  
        // 開始2秒 後巻き戻し(逆再生)  
        tween.PlayBackwards();  
        animator.SetFloat("Speed", -1f);  
        yield return new WaitForSeconds(2f);  
        // 開始4秒後 早送りへ  
        tween.timeScale = 2f;  
        animator.SetFloat("Speed", 2f);  
        // DOTweenを順再生にもどす  
        tween.PlayForward();  
    }
    

    最後にDOTweenを逆再生から順再生に戻すメソッドを紹介します。 PlayForward メソッドです。Tweenインスタンスに対して実行することで、逆再生から戻すことができます。

    PlayBackwardsとセット で覚えておくと良いでしょう。

    【注意】巻き戻し(逆再生)には落とし穴あり

    DOTweenの巻き戻し(逆再生)には 落とし穴 があります。
    巻き戻り完了後のTweenは、実は完了状態ではありません。

    【DOTween】巻き戻し(逆再生)と早送りする方法_13

    ※弊著 : DOTweenの教科書より
    巻き戻った状態はPause状態で停止します。

    つまり巻き戻ったときに何かしたい場合、 巻き戻し完了判定 を別途取得する必要があるということです。シンプルに取得する方法がないんですよね。

    このあたりについては 弊著「DOTweenの教科書」にて詳しく解説しています。
    興味ある方はぜひチェックしてみてください。

    📚 参考サイト : 📕DOPlayBackwards - 罠多し巻き戻しトゥイーン

    まとめ : DOTweenとAnimatorの「巻き戻し(逆再生)」「早送り」は分離して実装

    最後に記事の内容を簡単にまとめます。

    DOTweenとAnimatorの「巻き戻し(逆再生)」、「早送り」は分離して実装

    ①DOTweenの巻き戻し(逆再生)はPlayBackwardsを使う

    ②DOTweenの早送りはTweenのtimeScaleを使う

    ③Animatorの巻き戻し(逆再生)はAnimationStateのSpeedに負の値を代入

    ④Animatorの早送りはAnimationStateのSpeedに1より大きい値を代入

    こんな感じです。

    DOTween、Animator両方同時に考えると混乱しますよね。分離して考えれば意外と単純です。

    巻き戻し(逆再生)要望はそんなにありませんが、 早送りは意外と需要があります。

    というのも バトルの倍速モード ってゲーム作ってるとよく発生する仕様なんですよね。今回紹介した巻き戻し(逆再生)と早送りがゲーム開発の中で生きる可能性はあります。

    ぜひとも覚えていただければと。そして忘れてしまったらこの記事のことを思い出してみてください。

    あなたのゲーム開発に少しでもお役に立てたら嬉しいです。

    オススメ記事
    検証環境