DOTween完全に理解するその7 オプション編



前回：[DOTween完全に理解するその6 イベント編](https://qiita.com/BEATnonanka/items/a8c63df029f45ecf869d)

# 今回解説するもの

今回は各Tweenに設定できる「オプション」について解説していきたいと思います。
いくつかのオプションはかなりよく使うのでご存知の方も多いと思います。
一部使い所は限定的ですがかゆい所に手が届くものもあるので
覚えておくと意外なところで役に立つかもしれません。

**開発環境**
Unity:2019.4.0f1
DOTween:v1.2.335

# 今回解説するオプション

API|概要|
|---|---|
|SetAutoKill|アニメーション完了時にKillするか|
|SetRecyclable|KillしたTweenを再利用できるようにするか|
|SetUpdate|Tweenの更新スケジュールをどのタイミングにするか|
|SetRelative|アニメーションを相対的にするか|
|SetLoops|アニメーションがどのようにループするか|
|SetEase|アニメーションのイージングを設定|
|SetLink|TweenをGameObjectの状態に紐付ける|
|SetId|Tweenを管理するIdを設定|
|SetTarget|Tweenの対象となるターゲットの設定|
|SetDelay|Tweenの再生を遅延させるか設定|
|From|Tweenを設定値から現在の値へのアニメーションに変更する|
|SetSpeedBase|Tweenを速度ベースのアニメーションに変更する|
|SetAs|Tweenの設定値を上書きする|
|SetOptions|ジェネリックの各型専用オプション|

# システム的な動作に関わるオプション

Tweenのシステム的な動作を変更するオプションです。
最初に紹介する割に、あまり使う機会はありません。
ただ「Tweenはこういうルールで動いているんだな」と少し理解できるので最初に紹介します。

## SetAutoKill

```c#
tween.SetAutoKill(false); //アニメーション完了後に自動でKillしない
```

Tweenがアニメーションを完了した時に、自動でKillされるかを変更できます。
デフォルトの場合に自動でKillされるかどうかはDOTweenの設定によりますが
それを例外的に変更したい場合などに使用します。

個人的にはデフォルトで自動Killを有効にしておいて、
一部のアニメーションだけ使い回すことがわかっている場合``SetKill(false)``にしてます。

## SetRecyclable

```c#
tween.SetRecyclable(false); //TweenがKillされた後、このTweenを使いまわさない
```

KillされたTweenのその後の扱いを変更します。
基本的にDOTweenは内部的に**特定の値を初期値から目標値に向かって変更し続ける**というオブジェクトで動作しています。
そのため、目的が違っても使い方が同じ(型が同じ)な場合オブジェクトを再利用することで
オブジェクトを生成するコストを抑えています。
こちらもデフォルト設定から変更したい場合に使いますが
基本的に再利用が可能な状態で困ることはないので、使ったことはありません...

## SetUpdate

```C#
tween.SetUpdate(UpdateType.Late);        //LateUpdateのタイミングで動作する
tween.SetUpdate(UpdateType.Fixed, true);//FixedUpdateのタイミングで動作する(※要注意)
```

Tweenの更新タイミングを変更します。
これもあまり使い所はありませんが、`DOTween.To`でTweenを作成した場合に
「どうしてもLateUpdateのタイミングの値で処理したい」というシチュエーションがたまにあるので
そういったタイミングに役立ちます。

第２引数にtrueを指定した場合、**TimeScaleを無視して動作します**(デフォルトはfalse)
ただUpdateTypeFixedに設定した場合TimeScaleが0だと**FixUpdate自体が動作しないので注意が必要です。**

# アニメーションに関わるオプション

特にお世話になるオプションです。


## SetRelative

```c#
transform.DOMoveX(9, 1);　                  //1秒でx=9まで移動
transform.DOMoveX(9, 1).SetRelative(true);  //1秒で現在位置からx方向に9移動
```

アニメーションを「相対的」なものに変更します。
アニメーションさせたいオブジェクトの位置が変わっても、その位置から同じようにアニメーションさせたい場合に使えます。
後述の**再生後に設定しても反映されないオプション**の一つです。

動作に関しては[DOTween完全に理解するその2 Transformアニメーション編](https://qiita.com/BEATnonanka/items/b4cca6471e77466cec74#%E7%A7%BB%E5%8B%95)参照してください。

## SetLoops

```c#
tweenA.SetLoops(3, LoopType.Restart);      //はじめの状態に戻ってループ
tweenB.SetLoops(3, LoopType.Yoyo);         //逆再生を行うループ
tweenC.SetLoops(3, LoopType.Incremental);  //継続して同じ動きを繰り返す
```

![Loops1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203331/9b4102a3-6cd7-9da5-c2bc-c649368e20a2.gif)

**とてもお世話になるオプションその１です。**
アニメーションのループの仕方を設定します。
第1引数はループ回数、第2引数はループの種類
動作は画像の通りですがIncrementalがちょっと癖のある感じです。

SetRelative同様に**再生後に設定しても反映されないオプション**の一つです。

## SetEase

```c#
tween.SetEase(Ease.OutQuad);     //Settingsを変更していない場合のデフォルト
tween.SetEase(Ease.OutBounce);   //使っておけばいい感じになるEase代表
tween.SetEase(Ease.OutBounce, 3);//Bounceの幅を変更する(デフォルトは1.7ぐらい)
tween.SetEase(Ease.OutElastic);  //揺らしたい場合はこっち
tween.SetEase(Ease.OutElastic, 3, 0.0001f); //幅と周期の細かさ
```

![Ease.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203331/4974caa5-36a0-e2cd-8e9a-7dba457b055a.gif)


**とてもお世話になるオプションその２**
アニメーションにいい感じの緩急をつけてくれます。
DOTween側で用意されているEaseだけでほぼ事足ります。
ただどうしても自作したい場合は

```c#
tween.SetEase(AnimationCurve);  //AnimationCurveを指定する
tween.SetEase(EaseFunction);    //EaseFunctionを指定する
```

という方法もあります。
AnimationCurveであればSerializeFieldを使用することで、思った通りの動きをさせることができると思います。

注意点としてBack系やElastic系など**目標値を超えるEaseはDOPathではうまく動作しません**

各Easeがどのよう動きをしているかは、下記サイトが世界一分かりやすいのでおすすめです。
[DOTweenのイージング一覧を世界一詳しく&分かりやすく説明する](https://game-ui.net/?p=835)

# アニメーションと何かと紐付けるオプション

アニメーションと何かを関連づけて、特定のアニメーションだけ再生させたり
アニメーション対象の状態によって再生状態を変更したりできます。

## SetLink

```c#
tween.SetLink(targetA.gameObject); //デフォルト、DestroyとともにKillされる(KillOnDestroy)
tween.SetLink(targetB.gameObject, LinkBehaviour.RestartOnEnable); //Enable時にRestart
tween.SetLink(targetC.gameObject, LinkBehaviour.PauseOnDisable);  //Disable時にPause
```

**使用率No.1オプションだと思います。**
特に消滅するGameObjectをアニメーションさせる場合は必須と言っても過言ではないでしょう。
このAPIを使用しなかった場合、**削除されたオブジェクトへアニメーションを行おうとしてエラーになってしまいます。**

DOTweenをSafeModeで実行している場合、以下のようなエラーが出る場合は``SetLink()``しておく方がいいです。
SafeModeが気を使って教えてくれているだけで、特に問題ない場合もあります。

```
DOTWEEN ► Target or field is missing/null () ► The object of type 'Transform' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
```

![SetLink0.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203331/bf0ad4de-564b-1918-3485-cafba9c83ecc.gif)

設定一覧

|LinkBehaviour|説明|
|----|----|
|PauseOnDisable|非アクティブ時にPause|
|PauseOnDisablePlayOnEnable|非アクティブ時にPause<br>アクティブ時にPlay|
|PauseOnDisableRestartOnEnable|非アクティブ時にPause<br>アクティブ時にRestart|
|PlayOnEnable|アクティブ時Play|
|RestartOnEnable|アクティブ時にRestart|
|KillOnDisable|非アクティブ時にKill|
|KillOnDestroy|Destroy時にKill(デフォルト)|
|CompleteOnDisable|非アクティブ時にComplete|
|CompleteAndKillOnDisable|非アクティブ時にCompleteしてKill|
|RewindOnDisable|非アクティブ時にRewind|
|RewindAndKillOnDisable|非アクティブ時にRewindしてKill|

OnEnable系は**指定したGameObjectがすでにアクティブな場合、再生されてしまうので注意してください。**
また、``SetLink()``を行なった場合どのLinkBehaviourを指定してもKillOnDestroyと同じ動作が含まれています。

動作はこんな感じです。
1秒ごとにアクティブと非アクティブを切り替えています。

![SetLink1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203331/d3583241-6896-2de3-a036-45678ef5a59a.gif)
「PlayOnEnable」は非アクティブになっても関係なく動作します(ワープしてるみたいになってる)
「RestartOnEnable」はアクティブになるたびに最初から(結構便利)
「PauseOnDisable」は非アクティブ時にPauseされ、アクティブ時は何もしないので停止したまま
「PauseOnDisablePlayOnEnable」はアクティブになるとアニメーションを再開
「PauseOnDisableRestartOnEnable」は見た目はRestartOnEnableと同じですが厳密にはアニメーションが停止しているためちょっと違います

以下はDisable系の比較です。
1秒ごとに非アクティブし、1秒後に``DOTween.PlayAll()``しています
![SetLink2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203331/7d017497-e06f-b516-bee6-9c35050ce617.gif)
「KillOnDisable」は非アクティブ時にKillされるためアクティブになっても再生されず
「CompleteOnDisable」はCompleteされ、アクティブになっても再生されません
「RewindOnDisable」はRewindされているので最初の状態に戻っています
「CompleteAndKillOnDisable」はComplete状態になった上でKillされるためPlayBackwardsなどもできません
「RewindAndKillOnDisable」も同様にRewind状態になった上でKillされます

## SetId

```c#
tween.SetId(1);         //数値を指定する
tween.SetId("hoge");    //文字列を指定する
tween.setId(obj);       //objectを指定する

DOTween.Play("hoge");   //hogeだけ再生
```

TweenにIdを割り振ってグループ化することができます。
例えば``DOTween.Play()``などに引数で指定すると、対象のTweenのみ再生されます。
動作としては`int > sting > object`の順に速いです。

## SetTarget

```c#
tweenA.SetTarget(targetA);
tweenA.SetId(1);
tweenB.SetTarget(targetA);
tweenB.SetId(2);
tweenC.SetTarget(targetB);

DOTween.Play(targetA);      //targetAのTweenのみ再生
DOTween.Play(targetA, 1);   //targetAのId=1のTweenのみ再生
```

こちらは``SetId()``に加えて、さらにターゲットという範囲で判別する場合に使用できます。
``SetId()``だけで事足りる場合は``SetId()``の方を使用するのが推奨されています。

# 再生前に設定が必要なオプション

## SetDelay

```c#
tween.SetDelay(1f);     //1秒送らせて動作開始
```

アニメーションの開始を指定しただけ遅らせるオプションです。
「開始」を遅らせるというのがミソで、基本的にループの場合2度目のループ開始時には遅延されません。
``Restart()``や``Rewind()``を使用して初期状態に戻すことで再度遅延が有効になります。

ちなみに``Sequence.SetDelay()``は``Sequence.SetPrependInterval``と同じです。

## SetDelay(delay, asPrependedIntervalIfSequence)

```c#
tween.SetDelay(1f, true);     //1秒送らせて動作開始(ループしても有効)
```

Sequenceのみに有効なオプションです。
asPrependedIntervalIfSequence=trueに指定した場合**ループ毎にDelayが有効になります**

## From

```C#
tween.DOMoveX(8, duration);                 //x＝8まで移動
tween.DOMoveX(8, duration).From();          //x＝8「から」現在位置まで移動
tween.DOMoveX(8, duration).From(true);      //x=8に「座標を変更して」現在位置まで移動
tween.DOMoveX(8, duration).From(0, false);  //x=0からx=8へ移動
tween.DOMoveX(8, duration).From(0, true);   //x=0に「座標を変更して」x=8へ移動

//相対位置指定版
tween.DOMoveX(8, duration).From(true);            //x方向に8移動した位置「から」現在位置まで移動
tween.DOMoveX(8, duration).From(1, true, true);   //x方向に１移動した位置に「座標を変更して」x=8へ移動
```

「動作開始の値」を設定するオプションです。
全てのTweenで使用でき、各型を初期値として指定できます。
``immediately=true``に設定することで「再生前に」指定した値がセットされます。

文章では分かりにくいと思うので、以下のgifを参考にしてください。
![From.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203331/1d1e13a6-3014-2050-6089-c509efd9ad36.gif)


## SetSpeedBase

```c#
tween.DOMoveX(8, duration);                 //x=8まで3秒で移動
tween.DOMoveX(8, duration).SetSpeedBased(); //x=8まで秒速3で移動
```

Tweenを速度基準のアニメーションに変更します。
１秒間にdurationずつ値が変化していきます。
**SetEaseをしている場合、その影響を受けるので注意してください(等速にしたい場合はEase.Linerを指定)**
![SpeedBase1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203331/5ff6119e-d246-0cd4-334d-8f1d809bf9f0.gif)

# その他のオプション

## SetAs

```c#
tweenA.SetId(id);
tweenA.SetDelay(delay);
tweenA.SetLoops(3, LoopType.Yoyo);
tweenA.SetEase(Ease.InOutBack);

tweenB.SetAs(tweenA);   //tweenAと同じ設定にする

var tweenParam = new TweenParams();
tweenParam.SetId(id);
tweenParam.SetDelay(delay);
tweenParam.SetLoops(3, LoopType.Yoyo);
tweenParam.SetEase(Ease.InOutBack);

tweenC.SetAs(tweenParam);   //tweenParamの設定を適用する
```

Tweenに設定された設定を別のTweenにも適用するオプションです。
共通設定となるTweenParamをあらかじめ作成しておいて、一斉に適用するなどもできます。
上記の場合はどのTweenも同じようにアニメーションします。
SetAs後に個別に設定したオプションは当然個別に適用されます。

オプション以外に、イベントやtimeScaleなどの設定も適用されるので注意して下さい。
また**TargetとLinkは反映されないので注意してください。**
以下はその例です。
![SetAs.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203331/18b25a17-bfb1-2f49-84ab-8913f995f176.gif)
TargetAは``SetLink()``されており、一定時間後にDestroyされます。
TargetBは``SetAs(TargetA)``後に個別に``SetRelative()``しています。
TargetCは``SetAs(TargetA)``のみです(本来のTargetAと同じ動き)

TargetAがDestroyされた後も他のTweenは問題なく動作し続けます。

## SetOptions

Tweenの対象となっている型ごとに個別のオプションを指定できます。
以下は一例です

型|Tween|設定|効果|
|---|---|---|---|
|float|DoFadeなど|isSnapping|小数点以下を切り捨て|
|Color|DOColorなど|alphaOnly|アルファ値のみ影響を与える|
|Vector系|DOMoveなど|constraint<br>isSnapping|動作する軸の指定<br>小数点以下切り捨て|
|String|DOTextなど|richTextEnabled<br>scramble<br>scrambleChars|リッチテキストを使うか<br>ScrambleModeの指定<br>ランダムに表示されれる文字の指定(ScrambleMode.Custom時に使用)|
|特殊|DOPath|closePath<br>lockPosition<br>lockRotation|[DOTween完全に理解するその4 DOPath編](https://qiita.com/BEATnonanka/items/50cacac803f88f5074dd#setoption)|