12
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

『UniTask v2』の色々な .ToUniTask

Last updated at Posted at 2021-01-01

はじめに

UniTask にはあらゆるものを UniTask に変換する .ToUniTaskというメソッドがあります
同じものを変換するときでもオーバーロードがあったりでややこしいので備忘録としてまとめてみました
GetAwaiterWithCancellation なども書いておきます(実装を書くのは省きます)

UniTask/Github

環境

以下の環境で動作しています

  • Unity 2019.4.15f1
  • UniTask 2.0.37

目次

準備

ダミー変数
var token = this.GetCancellationTokenOnDestroy();
var uniTask = UniTask.Run(() => "hoge");

こんな感じで変数tokenは何かしらのCancellationTokenが、
変数uniTaskには何かしらのUniTaskが入っていると考えてください

CancellationToken

CancellationToken を UniTask に変換できます

ToUniTask

// 実装
public static (UniTask, CancellationTokenRegistration) ToUniTask(this CancellationToken cancellationToken)

// 使用例
var (task,registration) = token.ToUniTask();
registration.Dispose(); // CancellationTokenRegistrationから破棄もできる
await task;

CancellationToken がキャンセル状態になるまで await される UniTask が返ってきます
返り値は (UniTask, CancellationTokenRegistration) というタプルです

WaitUntilCanceled

UniTask型ではありませんが、awaitableなCancellationTokenの型が返ってきます

// 実装
public static CancellationTokenAwaitable WaitUntilCanceled(this CancellationToken cancellationToken)

// 使用例
await token.WaitUntilCanceled(); // 直接awaitできる。ToUniTaskはできない

逆変換

UniTask を CancellationToken に変換できます

// 実装
public static CancellationToken ToCancellationToken<T>(this UniTask<T> task)
public static CancellationToken ToCancellationToken<T>(this UniTask<T> task, CancellationToken linkToken)

// 使用例
var ct = uniTask.ToCancellationToken();
var ct2 = uniTask.ToCancellationToken(linkToken);

コルーチン

ダミーのコルーチン
private IEnumerator HogeCoroutine(){
    yield break;
}

ToUniTask , GetAwaiter , WithCancellation

UniTask では StartCoroutine を使わずにコルーチンを起動することができます
ただし、UniTaskはコルーチンの yield return new WaitForEndOfFrame()を再現できないので注意が必要です。

// 実装
public static UniTask ToUniTask(this IEnumerator enumerator, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))

// 使用例
await HogeCoroutine(); // コルーチン起動
await HogeCoroutine().ToUniTask(PlayerLoopTiming.FixedUpdate, token);
await HogeCoroutine().WithCancellation(token);

下記は MonoBehaviour を引数に渡すことで内部でStartCoroutineが走ります。なので yield return new WaitForEndOfFrame()も正常動作しますし、寿命もゲームオブジェクトと結びついてくれます。

// 実装
public static UniTask ToUniTask(this IEnumerator enumerator, MonoBehaviour coroutineRunner)

// 使用例
await HogeCoroutine().ToUniTask(this);

逆変換

UniTask を IEnumerator に変換できます

// 実装
public static IEnumerator ToCoroutine<T>(this UniTask<T> task, Action<T> resultHandler = null, Action<Exception> exceptionHandler = null)
public static IEnumerator ToCoroutine(this UniTask task, Action<Exception> exceptionHandler = null)

// 使用例
StartCoroutine(uniTask.ToCoroutine(Debug.Log,Debug.LogError));
StartCoroutine(uniTask.ToCoroutine(Debug.LogError));

エラーハンドリングや結果を得るためのデリゲートを渡せるオーバーロードが用意されてます

AsyncOperation

AsyncOperation を UniTask に変換できます

UniTask には 様々な AsyncOperation が awaitable になっています。

  • AsyncOperation
  • ResourceRequest
  • AssetBundleRequest
  • AssetBundleCreateRequest
  • UnityWebRequest

シグネチャは拡張メソッドのthisキーワードが付いた引数の型の違いしかなく、使い方は全部一緒なので省きます。

// 実装
public static UniTask ToUniTask(this AsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))

// 使用例
await SceneManager.LoadSceneAsync("Game");
await SceneManager.LoadSceneAsync("Game").ToUniTask(cancellationToken : token);
await SceneManager.LoadSceneAsync("Game").WithCancellation(token);
await SceneManager.LoadSceneAsync("HogeScene")
                  .ToUniTask(Progress.Create<float>(n => {
                      Debug.Log($"現在{n * 100}%");
                  }), PlayerLoopTiming.Update, token);

SceneManager.LoadSceneAsync の例です。
.ToUniTaskに Progress を入れて進行状況を取ることができます。

AsyncLazy

UniTask に用意されている AsyncLazy型です。ToUniTask ではなく .Taskプロパティ から取得できます

.Taskプロパティ

var lazy = UniTask.Lazy(() => uniTask);
var task = lazy.Task; // UniTaskに変換

逆変換

UniTask から AsyncLazy に変換できます

uniTask.ToAsyncLazy(); // AsyncLazyに変換

IObservable

IObservable を UniTask に変換できます。

ToUniTask

// 実装
public static UniTask<T> ToUniTask<T>(this IObservable<T> source, bool useFirstValue = false, CancellationToken cancellationToken = default)

// 使用例
await subject.ToUniTask(cancellationToken:token); // OnCompletedが発行されるまで待つ
await subject.ToUniTask(true,token); //次に発行される最初のメッセージを待つ

第一引数をtrueにすると、次に発行される最初のメッセージだけを待機できます。

逆変換

UniTask を IObservable に変換できます。

uniTask.ToObservable();

JobHandle

ジョブの実行が終了するまで待機できます

// 実装
public static UniTask ToUniTask(this JobHandle jobHandle, PlayerLoopTiming waitTiming)
public static async UniTask WaitAsync(this JobHandle jobHandle, PlayerLoopTiming waitTiming, CancellationToken cancellationToken = default)

// 使用例
await jobHandle;
 // CancellationTokenが指定できない
await jobHandle.ToUniTask(PlayerLoopTiming.FixedUpdate);
 // 指定したタイミングに切り替えてjobHandle.Complete();される
await jobHandle.WaitAsync(PlayerLoopTiming.FixedUpdate,token);

実装を見ればどれも違うのがわかりますが、自分はJobHandleに詳しくないので有識者の方、コメントや編集リクエストをお願いします!

AsyncGPUReadbackRequest

AsyncGPUReadbackRequest を UniTask に変換できます。

ToUniTask

// 実装
public static UniTask<AsyncGPUReadbackRequest> ToUniTask(this AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))

await AsyncGPUReadback.Request(src);
await AsyncGPUReadback.Request(src).ToUniTask(cancellationToken : token);
await AsyncGPUReadback.Request(src).WithCancellation(token);

逆変換

UniTask を AsyncGPUReadbackRequest に変換できます

var asyncGpuReadbackRequest = AsyncGPUReadback.Request(src);
asyncGpuReadbackRequest.ToUniTask(PlayerLoopTiming.FixedUpdate,token);

おわりに

文章書くの下手すぎて読みにくいかもです。すいません。
間違いがあったら優しく教えてください。

変更履歴

変更1(コルーチン)

とりすーぷさんからご指摘をいただきコルーチンの項目を少し書き換えました!ありがとうございます!

12
9
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
12
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?