LoginSignup
11
7

More than 3 years have passed since last update.

初心者向けコルーチンの代わり?UniTask(UniRx.async)を使い方

Last updated at Posted at 2019-06-08

自己紹介

こんにちはゆずです。@Yuzu_Unity

はじめに

この記事はUnityのコルーチンを扱える人が
UniTask(UniRx.async)を扱えるようになればいいと思って書いています。
非同期処理以外については触れていません。
UniRxは全く関係ないです。
この記事ではUniRxについては記述しません。

こういう人向け?

複数フレーム待つ動作を頻繁に使いたい人?
セーブデータなどのIO関係を触る人
コルーチンに戻り値が欲しいと思っている人
C#7.0で色々使えるようになりたい人

環境構築編

C#7.0環境 IDEであればVisualStudio2017 Rider等

Unity2018.3以上

GitHubでUniTask(UniRx.async)
https://github.com/Cysharp/UniTask
もしくは AssetStoreでUniRxダウンロード(現在はGitHub版推奨 UniRxとUniTaskは分離されるみたいです。)
https://assetstore.unity.com/packages/tools/integration/unirx-reactive-extensions-for-unity-17276
※UniRxとは別物ですが同じパッケージに入っている

.NET 4.xモードにする(Player Settings→Other Settings)
image.png

UniTaskとは

C#7.0でasync/await Taskを扱えるようになったが,
Unityが公式でサポートしておらずこのままではコルーチンの代わりとして扱えないので
それを解消するライブラリです。
つまり逆に入れないと思ったように動かないと思ったほうがいい⁉
(Taskがメインスレッドで動いていないので、メインスレッドで動くTexture2D.EncodeToPNGなどは動作しませんでした。)

使い方

書き方

実行 関数名();
関数 async void 関数名() { }

実行 await 関数名();
関数 async UniTask 関数名() { }

実行 変数 = await 関数名();
関数 async UniTask<戻り値の型> 関数名() { }

の3つ
IEnumerator と async void が大体同じです。

  • コルーチン

    void Start()
    {
        StartCoroutine(TestCoroutine());
    }
    IEnumerator TestCoroutine()
    {
        //WWWクラス定義
        WWW www = new WWW("http://urx3.nu/QwZk");
        //wwwダウンロード開始
        yield return www;
        Debug.Log("Complete");
    }

  • UniTask
//using UniRx.Async;

    void Start()
    {
        TestUniTask();
    }

    async void TestUniTask()
    {
        //WWWクラス定義
        WWW www = new WWW("http://urx3.nu/QwZk");
        //wwwダウンロード開始
        await www;
        Debug.Log("Complete");
    }

ほとんど変わらないですね
IEnumeratorがasync
yield returnが await
という感じですね

これではメリットがあまりわからないので複数フレーム待機、戻り値ありにしてみましょう

//using UniRx.Async;
   async void Test()
    {
        //TestUniTask終了まで待つ
        int a = await TestUniTask();
        Debug.Log("Complete");
    }


    async UniTask<int> TestUniTask()
    {
        //5フレーム待つ
        await UniTask.DelayFrame(5);
        return 3;
    }

複数フレームはコルーチンだと1フレームのループ処理になり
無駄な処理が挟まれて結構重かったりしますね。

キャンセル処理

UniTaskの最大のデメリットです

コルーチンではStopCoroutine()もしくは
コンポーネントをOFFで止まることができました。

UniTaskはコンポーネントをOFFにしても止まりません!!
なのでゲームオブジェクトを消しても動きつづけます。

キャンセル処理に関してはここを参照してください
https://qiita.com/toRisouP/items/4445b6b9bf00e49eb147#%E3%82%AD%E3%83%A3%E3%83%B3%E3%82%BB%E3%83%AB%E5%87%A6%E7%90%86

キャンセル処理するならコルーチン現役ですね…

まとめ

停止が面倒なので
普通のゲーム制作のみであればコルーチンのほうがいいが
複数フレーム待つ動作を頻繁に使うのであればUniTask

セーブデータ、AssetBundleのダウンロード書き込み等
IO関係はUniTaskを使うほうがC#に用意されている非同期系が使えるので良い

要は併用しようという感じですかね!

また、ここには書いていませんがマルチスレッドプログラムもかけるのでそこに関してはゲームでも実用できるかと思います。
C#jobsystemの制約は少しめんどくさいですしね

11
7
1

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
11
7