[Unity] DOTweenを使ってみよう

[PONOS Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ponos)の18日目の記事です。

昨日は @nisei275 さんの[RustとWebSocketで実現したリアルタイム通信環境にUnityで通信してみる](https://qiita.com/nisei275/items/a60cb3d3e97aeb429fa7)でした。

#はじめに
###DOTweenとは
DOTweenとはUnityで使用できる線形補間ライブラリ 自分が神アセットだと思うアセットの１つです。
読み方は「ドットゥイーン」
無料版と有料版のProがあります。

公式：http://dotween.demigiant.com/
AssetStore：https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676

###DOTweenを触るようになったきっかけ
かなり前の話ですが、cocos2d-xをメインにゲームを作っていました。
そんなcocos2d-xですが、標準でCocosActionという線形補間ライブラリが内蔵されています。

こんな感じのやつです。

```cpp:cocosAction.cpp
auto enemySprite = Sprite::create("enemySprite.png");
auto moveTo = MoveTo::create(2, Vec2(50, 0));

enemySprite->runAction(moveTo);
```

cocos2d-xからUnityをメインに触るようになってから iTween -> DOTween を使用してきました。

前置きが長くなりましたが今回はそんな神アセット「DOTween」の使用法をご紹介をしたいと思います。


#導入 -> 初期設定
・AssetStoreでDOTweenを入手 -> インポート
https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676

![Setup.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539810/99c5a3f4-3d95-3052-97c5-27ce45a8db04.png)

・Setupタブ
こちらでセットアップができます。

・Preferenceタブ
こちらで初期設定が変更できます。

![Initialize.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539810/ce6a7425-3ae2-1cc4-7e13-f6e23637af0b.png)
AutoPlayと初期EaseをLinearに変えておくと自分はやりやすかったです。

#実装
##Tweenの再生
Tweenの単発再生です。

```c#:TestTween.cs
using UnityEngine;
using DG.Tweening;

public class TestTween : MonoBehaviour
{
    // 現在再生中のTween
    Tween currentPlayTween;

    // 開始時
    void Start()
    {
        PlayMoveTween();
    }

    // Tweenの再生
    void PlayMoveTween()
    {
        // 移動時間
        float duration = 2f;

        // 移動値
        Vector3 endValue = new Vector3(10, 10, 0);

        // Tweenの作成
        currentPlayTween = transform.DOMove(endValue, duration);

        // 相対に切り替え
        currentPlayTween.SetRelative();

        // イーズタイプの指定
        currentPlayTween.SetEase(Ease.Linear);

        // 再生
        currentPlayTween.Play();
    }
}
```
###結果
上記のコードでは２秒間で現在位置から(10, 10, 0) の距離を移動します。
SetRelative()をつけると絶対位置から相対位置になります


##Sequence ~ Tweenの連結 ~
Tweenを連結し、より複雑なことができます

```c#:TestSequence.cs
using UnityEngine;
using DG.Tweening;

public class TestSequence : MonoBehaviour
{
    // 現在再生中のSequence
    Sequence currentPlaySequence;
    SpriteRenderer spriteRenderer;

    // 開始時
    void Start()
    {
        spriteRenderer = GetComponent<SpriteRenderer>();
        PlaySequence();
    }

    // Sequenceの再生
    void PlaySequence()
    {
        // 移動時間
        float moveDuration = 1f;

        // 移動の最終値
        Vector3 moveEndValue = new Vector3(10, 10, 0);

        // 待機時間
        float waitDuration = 1f;

        // 透過時間
        float fadeDuration = 1f;

        //  透過最終値
        float fadeEndValue = 0f;

        // 移動Tweenの作成
        Tween moveTween = transform.DOMove(moveEndValue, moveDuration).SetRelative().SetEase(Ease.Linear);

        // 透過Tweenの作成
        Tween fadeTween = spriteRenderer.DOFade(fadeEndValue, fadeDuration);

        // Sequenceを生成
        currentPlaySequence = DOTween.Sequence();

        // Sequenceの構築
        currentPlaySequence
            .Append(moveTween)
            .AppendInterval(waitDuration)
            .AppendCallback(()=>Debug.Log("AppendCallback()"))
            .Append(moveTween)
            .Join(fadeTween);

        // 再生
        currentPlaySequence.Play();
    }
}
```

`Append(tween)` ... Tweenの連結再生
`Join(tween)` ... Tweenの同時再生
`AppendInterval(float)` ... Tween終了時に空白の時間を設ける
`AppendCallback(action)` ... Tween再生時にコールバックを追加します

###結果
１秒かけて(10, 10, 0)移動し、１秒間待機し、ログを出し、１秒かけて(10, 10, 0)移動しながらアルファを０にします。

##任意の数値を線形補間する

```c#:DOTweenTo.cs
// 時間
float duration = 1f;

// 最終値
int endValue = 100;

// 現在の値
int currentValue = 0;

// Tweenの生成
currentPlayTween = DOTween.To
(
    () => currentValue,
    value => currentValue = value,
    endValue,
    duration
);
currentPlayTween.OnUpdate(() => Debug.Log(currentValue));

// 再生
currentPlayTween.Play();
```

###結果
１秒かけて任意の変数の値が 0 から 100 になります
時間のカウントダウンなどに便利です


##コールバック

特定のタイミングで処理を挟むこともできます

```c#:callback.cs
// 移動時間
float duration = 1f;

// 移動の最終値
Vector3 endValue = new Vector3(10, 10, 0);

// Tweenの生成
currentPlayTween = transform.DOMove(endValue, duration).SetRelative().SetEase(Ease.Linear);

// ループの指定
currentPlayTween.SetLoops(-1, LoopType.Incremental);

// コールバック群
currentPlayTween.OnPlay(() => Debug.Log("OnPlay()"));
currentPlayTween.OnUpdate(() => Debug.Log("OnUpdate()"));
currentPlayTween.OnKill(() => Debug.Log("OnKill()"));
currentPlayTween.OnPause(() => Debug.Log("OnPause()"));
currentPlayTween.OnComplete(() => Debug.Log("OnComplete()"));
currentPlayTween.OnStepComplete(() => Debug.Log("OnStepComplete()"));

// 再生
currentPlayTween.Play();
```

`OnPlay()` ... 再生した時
`OnUpdate()`... 数値が変わった時
`OnKill()` ... 破棄した時
`OnPause()` ... 一時停止した時
`OnComplete()` ... 完了した時
`OnStepComplete()` ... ループなど一節が完了した時

##Tweenの破棄

```c#:kill.cs
if (currentPlayTween != null)
{
    // Tweenの破棄
    currentPlayTween.Kill();
    currentPlayTween = null;
}
```
Tweenに対してKill()を呼んでやることでTweenを破棄できます

#おわりに
基本の使い方は以上です

そして今回ご紹介したTweenはほんの一部です
もしDOTweenに興味が出たらいろいろ調べて触ってみてください(*'ω'*)

明日は @FW14B さんです！