環境
- Unity5.5.2f
- DOTween v1.1.600
結論
Tween.OnStepComplete
を使おう
背景
- 例えば、以下のようなゲージ増加のTweenを用意する
-
OnComplete
を使用することで終了時にDebug.Log
が実行される
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Image))]
public class DOTweenTest : MonoBehaviour
{
private void OnEnable()
{
this.GetComponent<Image>()
.DOFillAmount(1.0f, 1.0f)
.OnComplete(() => Debug.Log("completed"))
.Play();
}
}
- これにループ処理を挟み、ゲージが貯まる度に挙動を挟みたい
- まずは以下のコードを実行してみる
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Image))]
public class DOTweenTest : MonoBehaviour
{
private void OnEnable()
{
this.GetComponent<Image>()
.DOFillAmount(1.0f, 1.0f)
.OnComplete(() => Debug.Log("completed"))
.SetLoops(-1, LoopType.Restart)
.Play();
}
}
- 上記のケースでは
OnComplete
での処理が実行されない - これは渋谷ほととぎす通信さんの 今一番個人的にアツいUnityのTweenエンジン『DOTween』の罠〜ループ編〜 で言及されている「永久ループ時はComplete状態に至らないのでOnCompleteは実行されない」という挙動に沿うものだ
Sequence.AppendCallback
- 次に試したのがSequenceでの対応
- Sequenceに関しては以下の記事にまとめた
- ループさせる挙動自体にコールバックを仕込むことで対応する
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Image))]
public class DOTweenTest : MonoBehaviour
{
private void OnEnable()
{
Sequence sequence = DOTween.Sequence()
.Append(this.GetComponent<Image>().DOFillAmount(1.0f, 1.0f))
.AppendCallback(() => Debug.Log("completed"))
.SetLoops(-1, LoopType.Restart)
.Play();
}
}
- 挙動的には問題なさそうである
- 但しこれもやはり問題があり
SetLoops(-1, LoopType.Yoyo)
に対応できていないということだ-
LoopType.Yoyo
は処理を折り返し実行する関数 (ヨーヨーみたいに)
-
- 手元で実行すると往路での
Debug.Log
は呼ばれるが、復路では呼ばれないことが確認出来た
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Image))]
public class DOTweenTest : MonoBehaviour
{
private void OnEnable()
{
Sequence sequence = DOTween.Sequence()
.Append(this.GetComponent<Image>().DOFillAmount(1.0f, 1.0f))
.AppendCallback(() => Debug.Log("completed"))
.SetLoops(-1, LoopType.Yoyo)
.Play();
}
}
Tween.OnStepComplete
- http://dotween.demigiant.com/documentation.php
- DOTween側で何かしら関数用意してそうだなぁと思ってドキュメント読んでいたら
OnStepComplete
を発見した -
a single loop cycle
が完了したときに発火してくれるコールバック - まさにこれだ!ということで試してみる
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Image))]
public class DOTweenTest : MonoBehaviour
{
private void OnEnable()
{
this.GetComponent<Image>()
.DOFillAmount(1.0f, 1.0f)
.OnStepComplete(() => Debug.Log("completed!"))
.SetLoops(-1, LoopType.Yoyo)
.Play();
}
}
- 意図通りの挙動になった!