Skip to content

Instantly share code, notes, and snippets.

@anzfactory
Last active January 13, 2023 01:57
Show Gist options
  • Save anzfactory/da73149ba91626ba796d598578b163cc to your computer and use it in GitHub Desktop.
Save anzfactory/da73149ba91626ba796d598578b163cc to your computer and use it in GitHub Desktop.
DOTweenの自分用メモ

DOTween

UnityでつかえるTweenエンジンです
Asset Store にも、もちろん並んでいます。

DOTween

基本的な使い方

基本的には3DならTransformに対して設定、
2D(uGUI)ならRectTransformに対して設定していきます。
(対象によって変わるところですが...)

using DG.Tweening;    // namespace の指定をわすれずに!

// 3D
this.gameObject.transform.DOMove(new Vector3(0f, 1f, 0f), 2f);
// 2D
this.gameObject.GetComponent<RectTransform>().DOMove(new Vector3(0, 1, 0), 2f);

以降の例では2D系として書いてますが3Dの場合は、
RectTransformTransformに置き換えれば同じなはずです。

移動

ObjectのPositionを変更するアニメーション
ワールド空間での位置で扱いたい場合はDOMove()で、
ローカル空間での位置で扱いたい場合はDOLocalMove()で行います

// 3秒かけてローカル座標(155,20)に移動
rectTransform.DOLocalMove(
    new Vector3(155f, 20f, 0),    // 移動終了地点座標
    3f                            // アニメーション時間
);

DOMove()も同様です。
第3引数にsnappingがありますが、これはデフォルトでfalseになっています
trueを指定すると、座標が常にintになるように実行されます
最終結果だけでなく、途中の移動座標もintになるので、
1x1マス単位で移動させたい場合に有効だと思います。
(2D系だとRPGで1マスずつ移動させる場合など)
そういう特殊な事情がない限りは、通常falseでいいと思います
(そっちのほうがなめらかな移動になると思いますので)

他にも、X座標だけ変更させて移動したいというようなものもあります
DOMoveX()DOMoveY()DOMoveZ()
DOMoveLocalX()DOMoveLocalY()DOMoveLocalZ()
など
これらの場合、指定するのはVector3ではなく、floatになります

拡大・縮小

ObjectのScaleを変更するアニメーション これで、大きくしたり小さくしたりできます

// 3秒かけて2倍の大きさに
rectTransform.DOScale(
    new Vector3(2f, 2f),     // 終了時点のScale
    3f                        // アニメーション時間
);

// 3秒かけて0.5倍(半分)の大きさに
rectTransform.DOScale(
    new Vector3(0.5f, 0.5f),     // 終了時点のScale
    3f                            // アニメーション時間
);

他にも、Xだけ変更させたいというものもあります
DOScaleX()DOScaleY()DOScaleZ()
これらの場合、指定するのはVector3ではなく、floatになります

回転

ObjectのRotationを変更することで回転させるアニメーションです

// 3秒かけて回転
rectTransform.DORotate(
    new Vector3(0f, 270f),    // 終了時点のRotation
    3f                        // アニメーション時間
);

第3引数にRotateModeを指定できます
デフォルトではRotateMode.Fastが設定されています
この状態で上記の例を実行すると
Rotation.yが 0->359->358->357->356->....->270 と、
現在のRotationから近い方から変更していきます
これを0から徐々に大きくしたい場合はRotateMode.FastBeyond360にすると
0->1->2->3->...->270 と変わっていきます
こういう違いも出てくるので覚えておくと良いです

RotateModeにはRotateMode.LocalAxisAddRotateMode.WorldAxisAddがありますが...
ちょっと理解出来ていないので説明は省きます。

他にも、DORotateQuaternion()というものもあります、
Vector3で扱いたいかQuaternionで扱いたいかで使い分ける
これらのローカルパターンもあります
DOLocalRotate()DOLocalRotateQuaternion()

プリセットアニメーション

上記に紹介したものを組み合わせて
いろいろなアニメーションを実現していくのですが
DOTween のほうでよく使われるようなものは
まえもって用意されているのでそれらの紹介

Jump

ジャンプしながら指定地点へ移動していくアニメーションセットです
DOJump()DOLocalJump()があります

rectTransform.DOLocalJump(
    new Vector3(100, 50),    // 移動終了地点
    30,                        // ジャンプする力
    10,                        // 移動終了までにジャンプする回数
    5f                        // アニメーション時間
);

GIF

Punch

振動アニメーション(?)というのか。。
指定された値と現在の値をいったりきたりするようなそんなアニメーション
DOPunchScale()DOPunchPosition()DOPunchRotation()

rectTransform.DOPunchScale(
    new Vector3(1.5f, 1.5f),    // scale1.5倍指定
    5f                            // アニメーション時間
);

GIF

Shake

指定した属性で不規則に変化させるようなアニメーション
DOShakeScale()DOShakePosition()DOShakeRotation()

rectTransform.DOShakeScale(
    5f    // アニメーション時間
);

GIF

各種オプション

Easing

アニメーションの変化具合を指定するタイプです
タイプはいろいろあるので、試してお好きなモノを選択すると良いです

rectTransform.DOMoveX(10, 3f).SetEase(Ease.InOutCirc);

それぞれのEasingがどういう挙動をするのか確認したい場合は、 こちらがおすすめです。
リスト表示で同時にグラフもあるので見やすい。
CSS+jsで表現されてはいますが、Easingは言語によって違うっていうことはないだろうから、
どういう変化をするのか確認するには十分。

DOTween はデフォルトでEase.InOutQuadが設定されているので
全てのアニメーションでEase.InOutQuadが適用されているはずです
デフォルトのEaseTypeを変更する場合はdefaultEaseTypeを設定することで可能です

Awake()
{
    DOTween.Init();    // ← コレないと効かない
    DOTween.defaultEaseType = Ease.Linear;
}

他にも設定できる項目があるので、
気になる方は調べてみては

Loop

アニメーションの繰り替えし指定

// 3回繰り返す
rectTransform.DOScale(new Vector3(2f, 2f), 3f).SetLoops(3);

延々と繰り返す場合は SetLoops(-1) と設定するとできます。
ただ、この場合適宜 Kill() してあげないと、GameObjectが死んでも動き続けて結果警告がでる...ということになるので注意が必要です。

Tweener tweener;

void Do()
{
    this.tweener = rectTransform.DOScale(new Vector3(2f, 2f), 3f).SetLoops(-1);
}

void OnDestroy()
{
    this.tweener.Kill();
}

イメージとしてはこういう感じです。

Delay

アニメーションを開始する待機時間の設定

// アニメーションを2秒待ってから開始
rectTransform.DOScale(new Vector3(2f, 2f), 3f).SetDelay(2);

Relative

基本的に DOTween のアニメーションは 絶対的 な指定です
DOMove()とかでは指定した地点に移動するアニメーションです
でもケースによっては、相対的 に指定したいケースがあると思います
「現在地点からX座標方向に30移動したい」というような
その場合はSetRelative()で指定できます

rectTransform.DOLocalMoveX(30f, 3f).SetRelative();

Callback

各タイミングでのコールバック

rectTransform.DOLocalMove(new Vector3(100.6f, 100.8f), 3f)
    .OnStart(() => {
        // アニメーション開始時によばれる
        Debug.Log("Start!!");
    })
    .OnUpdate(() => {
        // 対象の値(このケースだとlocalPosition)が変更される度によばれる
        Debug.Log("Updated:" + rectTransform.localPosition);
    })
    .OnComplete(() => {
        // アニメーションが終了時によばれる
        Debug.Log("Complete!");
    });

Sequence

各アニメーションを連結したり、同時に実行したりを制御します
それを担うのがSequenceです

var sequence = DOTween.Sequence();
sequence.Append(
    rectTransform.DOLocalMove(new Vector3(100.6f, 100.8f), 3f)
);
sequence.Append(
    rectTransform.DOScale(new Vector3(2f, 2f), 3f)
);

Append()でセットすることで、
移動 してから 拡大するというアニメーションができます

移動 しながら 拡大する同時に行いたい場合はJoinを使います

var sequence = DOTween.Sequence();
sequence.Append(
    rectTransform.DOLocalMove(new Vector3(100.6f, 100.8f), 3f)
);
// Join()で追加する
sequence.Join(
    rectTransform.DOScale(new Vector3(2f, 2f), 3f)
);

その他にも各ステップ間になにか処理をさしこんだり、
全体を通してのコールバックなんかもあります。

var sequence = DOTween.Sequence();
var scaler = imageRect.DOScale(new Vector3(1.2f, 1.2f, 1.2f), 2.0f);
var mover = imageRect.DOMoveX(-2.0f, 1.5f, false);

// sequence のセットアップ
sequence.Append(scaler);
sequence.AppendInterval(1.5f);       // 拡大処理が終了後1.5秒待機
sequence.AppendCallback(() => {      // 1.5秒待機後の処理
    Debug.Log("wait 1.5 sec");
});
sequence.Append(mover);

// sequence のコールバック(各ステップではなくて連結した全体のコールバックになる)
sequence.OnStart(() => {
    Debug.Log("Start!");
});
sequence.OnComplete(() => {
    Debug.Log("Complete!");
});

こういう感じで実行すると、
最初の拡大処理が始まる前にStart!というログが出力されて
その後拡大されて...それが終了後、1.5秒待機(何も起こらない)。
待機後、wait 1.5 secというログが出力されてから、移動開始される。
移動がおわるとComplete!というログが出力されて、一連のSequenceの処理が終わるという挙動になります

特殊系

Transform(RectTransform)とは直接関係ないけど便利なもの

UnityEngine.UI.Text

UnityEngine.UI.Textで使えるものがあります。
それが文字送りです(ゲームではおなじみのものです)

var text = this.gameObject.GetComponent<UnityEngine.UI.Text>();
var message = "あいうえおかきくけこさしすせそ";
text.DOText(
    message, 	// 表示したい文字列
    message.Length * 0.2f	// 全てを表示するのにかかる時間
);

時間を固定にしてしまうと、
文字数が少ないときと多いときで表示されるスピード感が全然ちがってしまうので、
文字数 × 1文字表示にかかる時間 という感じでやってます。

これだけで文字送り(1文字ずつ表示される)ができます。

AudioClip

サウンドに対しても実行できるものがあります。
DOFade()です。名前から分かる通り、音量を徐々に大きくしたり小さくしたりということができます。

var audioSource = this.gameObject.GetComponent<AudioSource>();
audioSource.DOFade(
    1.0,    // 音量(0〜1で)
    1.5f    // 時間(秒)
).OnStart(() => {
    audioSource.volume = 0.0f;
});

この場合だと無音状態から徐々に大きくなって1.5秒後に最大音量になる

カスタム

DOTween ではRectTransform以外にもいろいろなものを扱えます。
その場合はTo()を使っていきます

var image = this.gameObject.GetComponent<Image>();
// Imageの色変更
DOTween.To(
    () => image.color,                // 何を対象にするのか
    color => image.color = color,    // 値の更新
    Color.yellow,                    // 最終的な値
    3f                                // アニメーション時間
);

// Alphaだけを変えたい場合はこちらも
DOTween.ToAlpha(
    () => image.color,
    color => image.color = color,
    0f,                                // 最終的なalpha値
    3f
);

To()が扱えるのはさまざま...
今回のColorVector系RectTransformRectintdouble
などなど...
これをうまく使えばアニメーション以外でも利用できそうです

遅延実行

Unity で遅延実行といえばコルーチンをつかったり、Update() ないでゴニョゴニョして実現したりなど...
わりといろいろな方法があるとおもいますが、DOTween も遅延実行の機能を提供しています。

DOVirtual.DelayedCall(
    2.5f,   // 遅延させる(待機する)時間
    () => {
        // こちらに実行する処理
    }
);

これだけで、遅延実行ができるので、コルーチンをつかって書くよりかはだいぶ楽にかけるようになります。

@anzfactory
Copy link
Author

ZennでDOTweenの教科書があるので、そっち見るのがおすすめ。このgistでも事足りたとしても、一読する価値ある。

https://zenn.dev/ohbashunsuke/books/20200924-dotween-complete

一部のチャプター以降は有料だけど無料の項目でも基本的なところは十分だと思う。
各サンプルコードにgifで動きもわかるのでとてもいい。コードと言葉だけではいまいちどういう動きなのか分からんとかってなっているひとは特に。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment