UnityのUniTaskって何なの?
UniTaskはUnityケーム開発で非同期プログラミングを効率的に行うためのライブラリです。UniTaskはC#のTaskと同じように、非同期コードを簡単に書くことができるようにしますが、Unityの特性に合わせて特別に設計されています。
標準的なC#のTaskは、Unity環境での使用にはいくつかの問題があります。主な問題点は、メモリの使用とパフォーマンスです。C#のTaskは、各操作が新しいヒープメモリを割り当て、ガベージコレクション(GC)を頻繁に引き起こすため、パフォーマンスに影響を及ぼす可能性があります。
UniTaskはこの問題を解決します。UniTaskは、UnityのUpdateやFixedUpdateなどのフレームベースのイベントに同期して動作し、ガベージコレクションの発生を最小限に抑える設計になっています。これにより、Unityで非同期コードを効率的に書くことができます。
さらにUniTaskは、非同期メソッドの結果を待つためのasync/awaitパターンを完全にサポートしています。このパターンを使うと、コードが読みやすくなり、非同期のフローを簡単に理解できます。
その他にもUniTaskは、タスクのキャンセル、タイムアウト、エラーハンドリングなどの高度な機能も提供しています。これらの機能を使うと、より堅牢で信頼性の高い非同期コードを書くことができます。
ガベージコレクションは、なんかメモリを管理してくれるものだとよく聞くけど、頻繁に起きるのは良くないことのようだ。このへんは今後も調べてみたい。
ただそれが頻繁に起きるのはTaskというC#標準の非同期処理らしく、Unityではそれを適切に管理するためのUniTaskなるものが用意されている。
async/awaitパターンのサンプルコードを書いてほしい
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cysharp.Threading.Tasks;
public class SampleClass : MonoBehaviour
{
private async UniTaskVoid Start()
{
await PrintMessageAfterDelay("Hello, UniTask!", 2.0f);
}
private async UniTask PrintMessageAfterDelay(string message, float delayInSeconds)
{
await UniTask.Delay((int)(delayInSeconds * 1000)); // UniTask.Delayはミリ秒で時間を指定する
Debug.Log(message);
}
}
プログラムって順番に実行されるんじゃないの?awaitの意味って何?と以前は思っていましたが、Unityのようなプログラムってすごく複雑で、この処理一つが動いている間に他のプログラムが動かないとゲームが止まってしまうので、awaitを書くことでこの処理が動いている間でもゲームが動いている状態にするということなんですね。
例えばこのアプリを作っているときはOpenAIやVOICEVOXのAPIを使っていて、その応答がないと先に進められないので、そういうときにUniTaskを使ってasync/awaitで結果が返ってくるまで待つようなことをしていました。
コルーチンとどう違うの?
コルーチンとUniTaskはどちらもUnityで非同期処理を行うための手段ですが、それぞれ特性と利用シーンが異なります。以下にそれぞれの特性を比較してみます:
コルーチン
- Unityがネイティブでサポートしているため、追加ライブラリの導入が不要。
yield return null
やyield return new WaitForSeconds(1.0f)
など、非同期処理を書くための特殊な構文を提供。- しかし、エラーハンドリングが不十分で、例外が発生した場合でも呼び出し元にそれが通知されない。
UniTask
- UniTaskは外部ライブラリなので、導入が必要ですが、その分機能が豊富。
- C#の標準的な非同期パターン(async/await)に完全に対応しており、学習コストが低い。
- タスクのキャンセル、タイムアウト、エラーハンドリングなど、高度な非同期処理をサポート。
- ガベージコレクションの発生を最小限に抑える設計になっている。
どちらを使用するかは、プロジェクトの要件と開発者の好みによるところが大きいです。
一般的な非同期処理を行うだけであれば、Unityのコルーチンでも十分ですが、複雑な非同期処理を行う場合や、パフォーマンスを重視する場合、またはエラーハンドリングをきちんと行いたい場合は、UniTaskの方が適しています。
加えて、C#のasync/awaitパターンに慣れている場合、UniTaskの方が直感的で簡単に感じるかもしれません。ただし、UniTaskは外部ライブラリなので、そのメンテナンスと互換性も考慮に入れる必要があります。
正直、UniTaskを使っているとコルーチンを使う場面がなかったのと、ChatGPTが言う通りわかりやすく感じます。今のところは特に困っていないのでUniTaskだけで対応しようと思います。