はじめに
今回はUniTaskの完了をフラグで待機する処理を紹介します
環境は Unity 2021.3.25f1です
やり方
Taskが完了しているかはIsCompletedで取得することができます
using UnityEngine; using Cysharp.Threading.Tasks; using System.Threading; public class Test : MonoBehaviour { void Start() { Application.targetFrameRate = 60; } async UniTaskVoid Update() { if(Input.GetKeyDown(KeyCode.F)) { var task = TestFnuc(this.GetCancellationTokenOnDestroy()).AttachExternalCancellation(this.GetCancellationTokenOnDestroy());//TestFnuc起動 int frame = 0; //TestFnucが終わるまで待機 //他の記述方法としては下記のやり方がある //task.GetAwaiter().IsCompleted //task.Status != UniTaskStatus.Succeeded while (!task.Status.IsCompleted()) { await UniTask.Yield(cancellationToken: this.GetCancellationTokenOnDestroy());//これがないと同期的な処理になってUnityが止まるので注意 Debug.Log("TestFnuc実行中 frame[" + frame.ToString() + "]"); frame++; } } } async UniTask TestFnuc(CancellationToken Token) { Token.ThrowIfCancellationRequested(); Debug.Log("TestFnuc開始"); await UniTask.DelayFrame(120,cancellationToken: Token); } }
Statusは内部挙動を把握してない使用すると危険みたいなので、上記の方法を使用せずにWhenAnyを使用すれば似たようなことができるのでそちらを利用した方がよさそうです
using System.Collections.Generic; using UnityEngine; using Cysharp.Threading.Tasks; using System.Threading; public class Test : MonoBehaviour { CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); void Start() { Application.targetFrameRate = 60; } async UniTaskVoid Update() { if (Input.GetKeyDown(KeyCode.F)) { var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationTokenSource.Token, this.GetCancellationTokenOnDestroy()); await UniTask.WhenAny(TestFnuc(linkedTokenSource.Token), Print(linkedTokenSource.Token)); cancellationTokenSource.Cancel();//WhenAnyは片方が終了しても、もう片方はTaskが走り続けるのでキャンセルさせる await UniTask.Yield();//Printがキャンセルされるまで1fかかるので待機 Debug.Log("TestFnuc終了"); } } async UniTask Print(CancellationToken Token) { Token.ThrowIfCancellationRequested(); int frame = 0; while (true) { Token.ThrowIfCancellationRequested(); await UniTask.Yield(cancellationToken: this.GetCancellationTokenOnDestroy()); Debug.Log("TestFnuc実行中 frame[" + frame.ToString() + "]"); frame++; } } async UniTask TestFnuc(CancellationToken Token) { Token.ThrowIfCancellationRequested(); Debug.Log("TestFnuc開始"); await UniTask.DelayFrame(120,cancellationToken: Token); } }