#自己紹介
こんにちはゆずです。@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)
#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の制約は少しめんどくさいですしね