[Unity][DoTween]DoTweenで調べまくって辿りついた いくつかの事

#はじめに

この記事は[「Unity Advent Calendar 2016」](http://qiita.com/advent-calendar/2016/unity) の8日目の記事になります。

今回はこの一年で一番触り、一番調べたDoTweenについて書かせていただきます。

なお、DoTweenの導入や基本的な使用方法のネタは他に優良な記事がありますので
こちらでは割愛させていただきます。

また当方は三十路の後半にWebフロントエンジニアからUnityエンジニアに
JobChangeした新米Unityエンジニアであるため、至ら無いところが多々あるかと思いますが
何卒、ご理解くださいませ。


#概要

* Tweenのタイムラインをコントロール
* DoTween.Toのおさらい
* イージングの応用 - カーブをインスペクターで作成する


#Tweenのタイムラインをコントロール

Tweenのアニメーションを一時停止させたり、そこから再生させたり
あるいは最初からやり直したり、と単純にアニメーションさせるだけでは
要件を満たさない場面はたくさんあります。

あまり詳しく書かれてい無いのですが、DoTweenは非常に優秀で
このあたりも簡単に実装する事が可能です。

##前提
この節のサンプルはuGUI上にあるUIオブジェクトで行う事を
前提と致します。

##Unity Editer上の画面イメージ
画面イメージはこんな感じです。

![sample.png](https://qiita-image-store.s3.amazonaws.com/0/34785/c13b3826-a145-3a28-dfee-0096fb27c055.png)

##準備
まず、Tweenの対象のGameObject（動くオブジェクト）のRectTransformをインスペクターで取得出来るようにします。
次にSequence型のフィールドを用意します。
コードで書くとこんな感じです。

```csharp:sample.cs
    public RectTransform RT;      /**<インスペクターで対象のGameObjectのRectTransformを取得する*/
    private Sequence mySequence;  /**<Sequenceを格納するフィールドを用意*/
```
---
##一時停止
実行した時の状態（座標だとその位置）で停止します。

```csharp:Pause
mySequence.Pause();
```
---
##再生
再生です。
DoTweenの再生はTweenを実行すると再生されます。
その為、これを利用するのは上記で説明した一時停止を利用した場合などになります。

一時停止後に実行すると停止した状態から再生を開始します。

```csharp:Play
mySequence.Play();
```
---
##再スタート
Tweenの開始位置から再度Tweenを実行します。
※一時停止中でも同様の挙動になります。

```csharp:Restart
mySequence.Restart();
```

##破壊
こちらはSequenceを完全に破壊します。
実行後、GameObjectは実行したタイミングの状態で停止します。
尚、Sequenceが破壊されていますので、上記で説明した 再生、再スタートは当然ですが実行不可能になります。
※GameObjectは破壊されません。あくまでSequenceの破壊です。

```csharp:Kill
mySequence.Kill();
```

##まとめたサンプルコード
説明は割愛しますが
TweenさせるGameObject（動くオブジェクト）のRectTransformをインスペクターで取得。
「再生」「停止」「破壊」「最初から」はボタンオブジェクトで
Play(), Pause(), Kill(), Restart()
をそれぞれ実行するようにすると実行出来るかと思います。

```csharp:Sample01.cs
public class Sample01 : MonoBehaviour
{

    public RectTransform RT;
    private Sequence mySequence;

    void Start()
    {
         mySequence = DOTween.Sequence();
         mySequence.Append
        (
            RT.DOAnchorPosX(200.0f, 10.0f)
           .SetEase(Ease.InQuad)
           .OnComplete
            (
              ()=>processCompleted()
            )
        );
        mySequence.Pause();

    }


    public void Play()
    {
        mySequence.Play();
    }

    public void Pause()
    {
        mySequence.Pause();
    }

    public void Kill()
    {
        mySequence.Kill();
    }

    public void Restart()
    {
        mySequence.Restart();
    }

    //
    public void processCompleted()
    {
        mySequence.Restart();
        mySequence.Pause();
        RT.anchoredPosition = new Vector2(200f, 10.0f);
    }

}

```

#DoTween.Toのおさらい
DoTweenはDOMoveなどの拡張メソッドが豊富にあり、殆どの場合はそれで要件を満たすのですが
稀に拡張メソッドに無いものをTweenさせたい場合があります。

ちょっと有効な例が思いつか無いので、必要になった時に分かりやすいように
簡単なサンプルコードで解説致します。

##サンプルコード
```csharp:Sample02.cs
    public int Number = 0;

    // Tweenを実行
    void Start()
    {
        DOTween.To (() => Number, (n) => Number = n, 100, 10.0f);

    }

    // Logで変化を確認
    void Update()
    {
        Debug.Log("Number:" + Number);// "Number:0 〜Number:100
    }

```

このサンプルコードはLogを見るとNumberの中身が100まで10.0秒かけて増えていくのが
確認出来るただそれだけのコードです。

##DoTweenは、ラムダを使う
上記のサンプルコードの具体的に解説をしていきます。
該当部分のコードを抜粋致します。

```csharp:Sample02.cs　抜粋
DOTween.To (() => Number, (n) => Number = n, 100, 10.0f);
```
まず 見出しの通り DoTweenは、ラムダを使います。
ちょっと自分て的にはラムダが解りにくいので分解してみました（私だけ?）

```csharp:Sample02.cs　ラムダが解りにくいので分解
DOTween.To 
(
            () => Number,　     //何に
            (n) => Number = n,　//何を
            100,　              //どこまで(最終的な値)
            10.0f               //どれくらいの時間
);

```

任意のプロパティなどを扱えるので抑えておくと役に立つと思います。

##おまけ
かなりレアケースですが、私はAnimationで管理するアニメーションクリップを
Tweenさせると言うケースで私は利用しました。

```csharp:アニメーションクリップをTween
DOTween.To
(
    () => anim[name].time,
    (time) =>  anim[name].time = time,
    1.0f,
    0.5f
);
```

#イージングの応用 - カーブをインスペクターで作成する
最後はイージングのカーブをインスペクターで指定する為の方法です。
分かってしまうと簡単な事ですが、見つけるのにかなりの時間を費やしました。

今回は備忘録の意味も兼ねて書いておこうと思います。

---

##イージングの指定方法は三つ
まず、DoTweenでイージングを指定するSetEaseの説明を見直してみます。

[DoTween](http://dotween.demigiant.com/documentation.php#options)のドキュメントのSetEaseの説明の部分
を見てもらうと以下のような記載があります。

>SetEase(Ease easeType \ AnimationCurve animCurve \ EaseFunction customEase)

1. Ease easeType　一般的なイージングのタイプを設定する方法　今回は割愛mm
2. AnimationCurve animCurve ※これが今回お伝えした部分！
3. EaseFunction customEase イージングの計算式を自作する方法 今回は割愛mm

今回は2の AnimationCurveを指定する方法をお伝えしたいのでそれ以外は割愛致します。

##AnimationCurve型のフィールドを用意
ここからが本題です。
実際にAnimationCurve型を用意しカーブを指定する部分を解説致します。

以下は最初のSample01の内容を少し変更したコードです。

```csharp:Sample03.cs
public class Sample03 : MonoBehaviour
{

    public RectTransform RT;
    public AnimationCurve Curve;/**< Tweenのイージングのカーブ*/※ココ！
    private Sequence mySequence;

    void Start()
    {
         mySequence = DOTween.Sequence();
         mySequence.Append
        (
            RT.DOAnchorPosX(200.0f, 10.0f)
           .SetEase(Curve)※ココ！
           .OnComplete
            (
              ()=>processCompleted()
            )
        );
        mySequence.Pause();

    }
//省略
```

変更点を抜粋すると以下の部分になります。

```csharp:Sample03.csの抜粋
///インスペクターでカーブを指定出来るようにします
public AnimationCurve Curve;/**< Tweenのイージングのカーブ*/
///上記のカーブをSetEaseの引数に入れます。
SetEase(Curve)
```

##インスペクターでカーブを作成
以下の画像のようにインスペクターでカーブを指定できるようになります。

![curveBB.png](https://qiita-image-store.s3.amazonaws.com/0/34785/362e6a39-050e-a4d3-6dcc-c27f416642ad.png)

カーブのところをクリックして編集

![curveA.png](https://qiita-image-store.s3.amazonaws.com/0/34785/f08bd77c-b96a-6b65-12fd-6867d959fb6b.png)


よく考えれば分かりそうなものですが、これに気がつくのにかなりの時間を費やしました;

##インスペクターでカーブを指定出来ると何が良いの？
インスペクターで出来る事がなぜ良いのか？
それは、微妙なイージングの調整をGUIで行うことが出来る点です。
もし同じプロジェクトにアニメーターさんがいらっしゃるのでしたら、
細かい部分をお任せする事が出来ます。

これ地味に便利です。

アニメーションの細かい動きを全てアニメーション(クリップ)で作ってしまうと
数が膨大になります。

そのため動的に制御するわけですが、イージングを調整して繊細な動きをつけたい時は
プログラムでは難しいのでこういった場合非常に助かります。


#おわりに
個人的になかなか良い情報が見つからずに調べまくった内容を
まとめてみました。
間違っているところや、もっと良い方法などがありましたらコメント頂けると幸いです。


さて、明日の [「Unity Advent Calendar 2016」](http://qiita.com/advent-calendar/2016/unity) は [monry](http://qiita.com/monry)さん の記事になります。
よろしくお願い致します。