Unity
uGUI
dotween

DOTweenを使ってskip可能なアニメーションを作る

More than 1 year has passed since last update.

環境

Unity:5.3.7p4
DOTween:1.1.575

はじめに

skip可能なDOTweenアニメーションを作成することが多かったのでまとめておきます。UIはuGUIです。
仮のアニメーションということで経験値取得ダイアログのワイヤーフレームを作ってみました。
FullSizeRender 2.jpg

先にまとめ

using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;

public class GetExpSample : MonoBehaviour
{
    // ダイアログ
    [SerializeField]
    GameObject m_expDialog;
    // 経験値バー
    [SerializeField]
    Slider m_expSlider;
    // 経験値テキスト
    [SerializeField]
    Text m_expText;
    // 経験値GETボタン
    [SerializeField]
    GameObject m_getExpButton;
    // 画面全体を覆うskipボタン
    [SerializeField]
    GameObject m_skipButton;
    // 閉じるボタン
    [SerializeField]
    GameObject m_closeButton;

    // 現在の経験値 サンプルなので固定
    int m_currentExp = 0;
    // レベルアップに必要な経験値 サンプルなので固定
    int m_maxExp = 1000;

    void Start()
    {
        m_expDialog.SetActive(false);
        m_skipButton.SetActive(false);
    }

    /// <summary>
    /// 経験値を取得する
    /// </summary>
    /// <param name="gotExp">取得した経験値</param>
    void GetExp(int gotExp)
    {
        float addSliderValue = (float)gotExp / (float)m_maxExp;
        float resultSliderValue = m_expSlider.value + addSliderValue;

        // メーターを増加する演出
        float getExpAnimTime = 2f;
        Sequence m_sequence = DOTween.Sequence().
            OnStart(() => {
                m_getExpButton.SetActive(false);
                m_skipButton.SetActive(true);
                m_expDialog.SetActive(true);
                m_expDialog.transform.localScale = Vector3.zero;
                m_closeButton.SetActive(false);
                m_expText.text = gotExp.ToString();
                }).
            Append(m_expDialog.transform.DOScale(Vector3.one, 0.2f)).
            AppendInterval(0.2f).
            Append(DOTween.To(
                () => gotExp,                           // 開始値
                exp => m_expText.text = exp.ToString(), // 値を更新する
                0,                                      // 最終値
                getExpAnimTime                          // アニメーション時間
            )).
            Join(DOTween.To(
                () => m_expSlider.value,                // 開始値
                value => m_expSlider.value = value,     // 値を更新する
                resultSliderValue,                      // 最終値
                getExpAnimTime                          // アニメーション時間
            )).
            AppendInterval(0.2f).
            OnComplete(() => {
                m_getExpButton.SetActive(true);
                m_skipButton.SetActive(false);
                m_closeButton.SetActive(true);
                m_expSlider.value = resultSliderValue;
                m_expText.text = "0";

            });
        m_sequence.Play();
    }

    /// <summary>
    /// 演出中画面タップ
    /// </summary>
    public void OnScreenTap()
    {
        // sequenceを切りつつ、OnCompleteを呼ぶ
        DOTween.KillAll(true);
    }

    /// <summary>
    /// 閉じるボタンタップ
    /// </summary>
    public void OnCloseButton(){
        m_closeButton.SetActive(false);
        m_expDialog.transform.DOScale(Vector3.zero, 0.1f);
    }

    /// <summary>
    /// 経験値取得ボタンタップ
    /// </summary>
    public void OnGetExpButton()
    {
        GetExp(200); // 仮に200exp取得する
    }
}

skip.gif

解説

Sequenceを破棄しつつOnCompleteを呼ぶ

経験値GETボタンタップ時に画面全体を覆う透明なskipボタンをActiveにしています。
skipボタンタップでSequenceをKillし、その際にOnCompleteを呼び出しています。

    /// <summary>
    /// 演出中画面タップ
    /// </summary>
    public void OnScreenTap()
    {
        // sequenceを切りつつ、OnCompleteを呼ぶ
        DOTween.KillAll(true);
    }

なので、OnCompleteにはアニメーション終了時と同じ状況になるように各GameObjectやvalueを設定するよう記述しています。

特定のアニメーションのみをskipしたい場合

今の書き方だと全てのtweenを破棄します。
tweenを特定したい場合はIdを指定すると良いです。

    void GetExp(int gotExp)
    {
        ...
        Sequence m_sequence = DOTween.Sequence().
            SetId("getSequence").   // idを設定する
            ...
    }
    ...

    public void OnScreenTap()
    {
        // 特定のidのtweenを全て破棄しつつ、OnCompleteを呼ぶ 
        DOTween.TweensById("getSequence").ForEach((tween) => tween.Kill(true));
    }

または、Sequenceをメンバー変数にしても特定できます。

m_sequence.Kill(true);

Sequenceを破棄したくない場合

sequenceは使いまわすからとっておいて、アニメーション終了&OnCompleteだけ呼び出したい時。

m_sequence.Complete(true);

さいごに

skipするためだけの仮の演出を作り始めたのですが、レベルアップ演出を挟むには...とか、SEとテクスチャをあてたいな...とか、想定していなかったことを始めそうでした。
何かの学習と絡めてレベルアップダイアログ出せるようにしたいなぁ。
あと、Hierarchyってどう共有すれば良いんでしょう?