LoginSignup
1
3

DOTWeenでToUniTaskを使う時にOperationCanceledExceptionが呼ばれない場合がある話

Last updated at Posted at 2022-02-17

初めに

await tweener.ToUniTask(cancellationToken:cancellationToken);

のようなコードを書いたらcancellationTokenのキャンセル時にOperationCanceledExceptionが発生しませんでした。どうやら引数によって発生の有無が変わるようなので挙動を調べました。

環境

  • Unity2020.3.19f1
  • UniTask 2.2.5

Tween.ToUniTaskのOperationCanceledException発生の有無

UniTask+DOTWeenでキャンセル処理をしたい場合、ToUniTaskメソッドでcancellationTokenを指定しますが、下のようなコードだと移動中にcancellationTokenがキャンセルされてもOperationCanceledExceptionが呼ばれず、以降の行が実行されて"Done"が出力されます。

public class Hoge : MonoBehaviour
{
    private CancellationTokenSource _cancellationTokenSource;
    
    async void Start()
    {
        _cancellationTokenSource = new CancellationTokenSource();
        
        MoveTask(cancellationToken:_cancellationTokenSource.Token).Forget();
        // 1秒後にキャンセル
        await UniTask.Delay(1000, cancellationToken: _cancellationTokenSource.Token);
        _cancellationTokenSource.Cancel();
    }

    private async UniTask MoveTask(CancellationToken cancellationToken)
    {        
        try
        {
            Tweener tweener = transform.DOMove(new Vector3(2, 3, 4), 3);
            await tweener.ToUniTask(cancellationToken:cancellationToken);
        
            Debug.Log("Done");
        }
        catch (OperationCanceledException e)
        {
            Debug.Log(e);
            throw;
        }
    }
}

DOTWeenのToUniTaskの引数にはキャンセル時の挙動を決めるtweenCancelBehaviour引数があり、その引数によってOperationCanceledException発生の有無が変わります。

tweenCancelBehaviour引数 OperationCanceledExceptionの発生
Kill(デフォルト) なし
Complete なし
CancelAwait あり
CompleteAndCancelAwait あり
CompleteWithSeqeunceCallback なし
KillAndCancelAwait あり
KillWithCompleteCallback なし
CompleteWithSeqeunceCallbackAndCancelAwait あり
KillWithCompleteCallbackAndCancelAwait あり

例えば下のコードのようにTweenCancelBehaviour.Completeを指定すると、cancellationTokenのキャンセル時にTweenが終了時の状態になり、OperationCanceledExceptionは発生しません。

public class Hoge : MonoBehaviour
{
    private CancellationTokenSource _cancellationTokenSource;
    
    async void Start()
    {
        _cancellationTokenSource = new CancellationTokenSource();
        
        MoveTask(cancellationToken:_cancellationTokenSource.Token).Forget();
        // 1秒後にキャンセル
        await UniTask.Delay(1000, cancellationToken: _cancellationTokenSource.Token);
        _cancellationTokenSource.Cancel();
    }

    private async UniTask MoveTask(CancellationToken cancellationToken)
    {        
        try
        {
            Tweener tweener = transform.DOMove(new Vector3(2, 3, 4), 3);
            await tweener.ToUniTask(tweenCancelBehaviour:TweenCancelBehaviour.Complete, cancellationToken:cancellationToken);
        
            Debug.Log("Done");
        }
        catch (OperationCanceledException e)
        {
            Debug.Log(e);
            throw;
        }
    }
}
1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3