Help us understand the problem. What is going on with this article?

DOTween完全に理解するその6 イベント編

前回:DOTween完全に理解するその5 Sequence編

今回解説するもの

今回はDOTweenのイベントについて解説していきたいと思います。
イベントはTweenに特定のタイミングで処理を挟むのに有効ですが、
設定や状況によっては想定と違う動作を起こすので注意が必要です。

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

イベント登録API

API 概要
OnStart 動作開始時に1度だけ呼ばれる
OnPlay 動作開始時に毎回呼ばれる
OnUpdate 動作中毎フレーム呼ばれる
OnPause 動作停止時に毎回呼ばれる
OnComplete 正方向の動作完了時に呼ばれる
OnStepComplete 動作完了時に呼ばれる
各ループの完了時にも呼ばれる
OnRewind 初期位置に戻った時に呼ばれる(PlayBackwardsなどで逆再生した場合も含む)
OnWaypointChange DOPathで各Pathに到達した時に呼ばれる
Pathのインデックスが引数で
OnKill Tweenが破棄される時に呼ばれる(Tweenがリサイクルされる場合も呼ばれる)

各イベントの特徴

OnStart

動作開始時に1度だけ呼ばれます。
それ以降はRestart()Rewind()を使用しても呼ばれることはありません。
また、TweenにDelayがかかっていた場合Delayが終わった後に呼ばれます。
(個人的にはこれが少し使いづらいかなと思う時もあります...)
Play()などを行わずにComplete()で終端まで実行した後PlayBackwards()などで逆再生した場合にも呼ばれます。
Sequenceの場合は先頭にAppendInterval()PrependInterval()をした場合でも
動作開始時にOnStartが呼ばれます(OnPlayも同様)

OnPlay

停止状態から動作開始した時に毎回呼ばれます。
OnStartと同様にDelayの影響を受けます。
PlayForward()PlayBackwords()SmoothRewind()など
停止中に動作を開始するAPIが呼ばれた場合にイベントが呼ばれますが、
動作中にこれらのAPIで再生方向が変わったとしてもOnPlayは呼ばれません。
また、すでにOnPlayが呼ばれた状態でGoto(andPlay:true)を呼んだ場合もOnPlayは呼ばれません。

OnUpdate

動作中に呼ばれます。
ただあまり使うシチュエーションは無い印象です。
OnStartと同様に通常のTweenの場合はDelayの影響を受け、
Sequenceの場合はDelay(Interval)の影響を受けません。

OnPause

動作停止時に呼ばれます。
AutoKill=falseの場合は動作完了時にも呼ばれる為、
OnCompleteOnStepCompleteとタイミングがシビアになります(後述)
AutoKill=trueの場合は動作完了時にOnKillが呼ばれOnPauseは呼ばれません。

OnComplete

動作完了時に呼ばれます。
ただ、通常再生の場合にのみ呼ばれPlayBackwards()などで逆再生の場合は
動作完了時であっても呼ばれません。
また、Complete()実行時にも呼ばれます。

OnStepComplete

動作完了時に呼ばれ、通常再生、逆再生に関わらず呼ばれます。
SetLoop()で設定したループの一動作が終わる度に呼ばれます。
Complete()Rewind()Goto()などで動作が終了した場合は呼ばれません。

OnRewind

Tweenが初期位置に戻った時に呼ばれます。
初期位置というのは経過時間が0秒の位置のことを指します。
PlayBackwards()SmoothRewind()でアニメーションが終わった場合に呼ばれますが
LoopType.Restartでアニメーションがループされる場合は呼ばれません。
また、Rewind()実行時にも呼ばれます。

OnWaypointChange

DOPath限定のイベントです。
DOPath生成時に設定したPathに到達した時に呼ばれます。
引数にPathのインデックスが渡されてきます。
SetOption()でClosePath=trueだった場合などでIndexが変わります(後述)

OnKill

Tweenが破棄される時に呼ばれます。
破棄される時と言ってもTweenがRecycable=trueでも呼ばれます。
再生されていない状態でComplete()を実行した場合にも呼ばれます。
AutoKill=falseの場合は動作完了時にOnPauseが呼ばれOnKillは呼ばれません。

注意すべきイベントの挙動

動作完了時に呼ばれるイベント群とその優先順位

通常の再生の場合はOnStepCoplete > OnComplete > OnKill/OnPauseの順で呼ばれます
tween_event1.gif
逆再生の場合はOnRewind > OnStepComplete > OnPauseの順で呼ばれます。
tween_event2.gif
よくあるパターンとしてスライドインしてくるUIを作った場合は
OnCompleteに通常再生の終了処理を書いて、OnRewindに逆再生の終了処理を書くのが良いかなと思います。

Sequence内のTweenのイベント

以下はイベントを設定したTweenに直接SetLoop()でLoopType.Yoyoを設定しています。
各Loop終了時にOnStepCompleteが呼ばれていることが確認できます。
tween_event3.gif

以下は同じイベントを設定したTweenをSequenceにAppendし、SequenceにSetLoop()を行なっています。
tween_event4.gif
各Loop終了時にOnCompleteOnRewindが発生するようになっています。
このようにSequence内にあるTweenのイベントは個別に状況に合わせたイベントが呼ばれます。

OnWaypointChangeのindex

OnWaypointChangeの引数として来るindexはDOPathの設定によって変わります。

一般的な場合(ClosePath=false、ループなし)

index 場所
0 初期位置
1 Path[0]
2 Path[1](終了位置)

tween_event_path1.gif

ClosePath=trueの場合

ClosePath=trueの場合、終了位置が初期位置になりますがその場合は
Indexが0ではなくPath総数+1になります。

index 場所
0 初期位置
1 Path[0]
2 Path[1]
3 終了位置(初期位置)

tween_event_path2.gif

ClosePath=trueでLoopする場合

ClosePath=trueでSetLoopを設定した場合は複雑になります
LoopType.Restartの場合はLoopなしの時と同じように
Restartした初期位置はIndex=0で終了位置はPath数+1になります。
tween_ecent_path3.gif
LoopType.Yoyoの場合は
逆再生する直前のIndexはPath数+1となり、逆再生中は各PathのOnWayPointChangeは2回ずつ呼ばれる
という挙動になります。
tween_event_path4.gif
この2回ずつ呼ばれるという挙動が結構曲者で、ドキュメントにも特に何も書いてないので
もしかしてバグなんじゃ...なんて思います。
同じIndexのコールバックは無視するような対応を行い、OnStepComplete時に無視フラグをリセットするような実装が必要になるかと思います。

まとめ

イベントはエフェクトを表示したり、入力の受付状態の切り替えなど
DOTweenとは別の仕組みと連携するために使用されることが多いと思います。
特にOnStepCompleteOnPauseOnRewindなどは使うシチュエーションはよく使うことになるので
DOTweenを応用して使う場合は身につけておくべき要素ですね。

余談ですがこの記事を書いていた7/29に
DOTweenの新バージョン(1.2.420)がAssetStoreで公開されたようです。
async/await対応
Sequence向けのSetDelayの拡張
ゲームでよく使いそうなカウントを使用するDOCounter
1文字ずつにアニメーションを行えるDOTweenTMPAnimator
などの良さそうな変更がかかっているようです。
特にDOTweenTMPAnimatorがかなり強力そうなのでこれを機にPRO版を購入しようと思います。

BEATnonanka
Uniny次元に生息しているマン クライアントエンジニア 社会の荒波の中でアプリ作ったり、運営したりしてます。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away