こんにちは、Unityエンジニアのオオバです。
Unityを使ってゲームを作るときにはどうしても、タイミングを調整したいという場面が登場します。
- ボタンを押して1秒後にキャラクターを登場させたい
- 演出が終わってから2秒後に宝箱のふたを開けたい
- 複数のアニメーションが終わってから次の演出を再生させたい
といった感じです。
Unityで提供されているのは、コルーチンとTask(タスク)です。しかし、コルーチン、Taskともに使い勝手が良いものではありません。今の主流は UniTask 。Unityに最適化されたTaskということで「UniTask」です。
オオバはスマートフォンゲーム業界に10年以上いますが、 UniTaskなしで開発は考えられないくらい重要な存在 になっています。UniTaskなしで開発すると開発期間が大幅に伸びることは間違いありません。
この記事ではUnityを使う上で重要なUniTaskについて、 インストール方法 から 基本的な使い方 までを解説しています。ぜひ最後まで読んでUniTaskを使えるようになってみてください。
本記事は、以前執筆したUniTask導入記事をより詳細に書き直した記事です。
👉DOTweenの教科書を読んでUnityアニメーションをプログラミングしてみよう!
UniTaskとは?
そもそもUniTaskとは株式会社CySharpが提供するオープンソースのライブラリです(だれでも無料で使用できるソースコード)。さまざまなUnity製タイトルで採用実績があるため非常に安心感があります。GitHubのスター(いいね数)も 6.2k と脅威の数値です。
これだけの評価を受けているライブラリですので、この記事を読んでいるあなたも 安心して 使ってみていただければと思います。
UniTaskのインストール方法
まずはUniTaskのインストール方法を紹介します。
いくつか方法がありますが、今回は最も簡単な Package Managerを使った方法 を紹介します。
Window > Package Manager
からPackage Managerウィンドウを開きます。 Package Managerウィンドウの左上の「+」ボタンをクリックして、 Add package from git URL を選択します。
入力フォームが表示されるので、次のURLを入力します。
https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask
入力が終わったら 「Add」ボタンをクリック。するとUniTaskはインストールされます。
以上で、UniTaskのインストールは完了です。
UniTaskの基本的な文法
UniTaskをインストールしたら、次はUniTaskの基本的な文法について学んでいきましょう。
いきなりUniTaskを使ったソースコードを紹介します。
次のコードを実行すると、3秒後にオブジェクトが左から右へ移動します。
transform.localPosition = new Vector3(-1f, 0, 0);
await UniTask.Delay(3000);
transform.localPosition = new Vector3(1f, 0, 0);
2行目のawait UniTask.Delay(3000);
によって3秒処理が待機されていることになるのです。
ここで登場した「await」と「UniTask.Delay」について次の章で解説します。
UniTaskの処理を待機する「await」とは
awaitとはC#に実装されている機能で 非同期処理を待機する役割 を持ちます。UniTaskだからawaitが使えるわけではなく、C#に実装されている非同期クラス「Task」でも同様にawaitを使えます。awaitがどのような時に使用されるのかというと、 処理を待機したい場合 です。
先の例だと、3秒処理を待機しました。もし、awaitがなかった場合は待機せずそのままオブジェクトは右側へ移動します。 「待機したいときにはawaitを使う」 と覚えておきましょう。
任意の時間、処理を待機する「UniTask.Delay」とは
UniTask.Delay
は非常によく使われるUniTaskのメソッドです。先のawaitとセットで利用します。
UniTask.Delayメソッドの引数にはミリ秒の値が入ります。
例えば UniTask.Delay(1)
とすると1ミリ秒待機するということです。
ただ、ミリ秒で指定するのは正直わかりづらいですよね。そこで TimeSpan
型を引数に指定することが可能です。
具体的には次のようなコードです。
await UniTask.Delay(TimeSpan.FronSeconds(3f));
3秒待機するUniTaskの処理に TimeSpan型 を利用した例です。
TimeSpan.FromSeconds
メソッドを使用することで、本来3000と入力しないといけないところが、3fと秒単位の値を入力することができるのです。
オオバも 実践ではミリ秒で指定することはありません。基本的にはTimeSpanを利用しています。 この方が後からソースコードを読んだ人もわかりやすいですしね。
UniTaskで重要な「async」キーワード
次にawaitとセットで覚える必要のある 「async」 について学びます。
UniTaskの文法として awaitを使う場合は、必ずメソッド宣言時にasyncを付ける必要がある のです。文字だけではわかりづらいので、次のソースコードを見ていきましょう。
※わかりやすくするために関数名を日本語にしています。
async UniTask 関数A()
{
await 関数B();
// 関数Bのあとに実行したい処理
}
UniTask 関数B(){ /*省略*/ }
上記のコードを図解すると以下のような説明になります。
つまり、関数Aの中で「await」を使用する場合は、関数Aに「async」をつける必要があるということです。
繰り返しになりますが 「awaitを使う場合は、必ずメソッド宣言時にasyncを付ける必要がある」 ということを覚えておきましょう。
次の章で実際にサンプルコードや事例を通して学んでいきます。
具体例をもとにUniTaskの基本的な使い方を学ぶ
ここからはいくつかの具体的な事例をもとにUniTaskの基本的な使い方を紹介します。
①赤色だったImageオブジェクトが2秒後に青色に変わるUniTask
②条件を満たすまで待機するUniTask.WaitUntilメソッド
③DOTweenの終了を待機して次のDOTweenを実行するUniTask
①赤色だったImageオブジェクトが2秒後に青色に変わるUniTask
次のコードはImageコンポーネントの色が2秒経過で赤から青に変わるサンプルです。
[SerializeField] private Image _image;
private async UniTask RedToBlue()
{
// ① Imageオブジェクトを「赤」へ
_image.color = Color.red;
// ② 2秒間処理を待機
await UniTask.Delay(TimeSpan.FromSeconds(2f));
// ③ Imageオブジェクトを「青」へ
_image.color = Color.blue;
}
たった3行で実装できます。
実行するとこんな感じです。
UniTaskを使用することで、処理が行ったり来たりせず直列に上から下に処理を記述できます。
上から順に処理を読むことができるため、非常に見やすいソースコードを維持できます。
②条件を満たすまで待機するUniTask.WaitUntilメソッド
UniTaskの便利なメソッドの1つ「WaitUntil」を紹介します。
WaitUntilは任意の条件を満たす前で処理を待機するメソッドです。ソースコードから確認していきましょう。
bool _isClicked;
private async UniTask CheckClick()
{
await UniTask.WaitUntil(() => _isClicked);
Debug.Log("クリックされました");
}
変数「_isClicked」がtrueになるまで待機するサンプルを作りました。
「〜〜するまで待機する」といった処理はゲームを作っていると死ぬほど発生します。そんなときのレシピの1つとして覚えておくと良いでしょう。
ゲーム開発現場ではよく登場します。
③DOTweenの終了を待機して次のDOTweenを実行するUniTask
UniTaskはDOTweenとの連携も公式にサポートされています。
DOTweenとはソースコードでアニメーションを実装する便利なアセットです。約10年ほど長きに渡ってさまざまなタイトルで使用されています。非常に採用実績が多く安定したライブラリと言えるでしょう。
次のコードではDOTweenをUniTaskで制御したサンプルです。
Transformオブジェクトが1秒かけて座標 (0, 1f, 0)
に移動した後、座標(1f, 0, 0)
に0.5秒かけて移動すするサンプルです。
private async UniTask DOTweenUniTask()
{
await transform.DOLocalMove(new Vector3(0, 2f, 0), 1f);
await transform.DOLocalMove(new Vector3(2f, 1f, 0), 0.5f);
}
今回は非常にシンプルなサンプルでしたが、複雑なアニメーションを実装するときにもUniTaskは非常に強力です。
注意点として、DOTweenをUniTaskで制御するときには初期設定が必要です。何もしなければエラーが出てしまいます。
このあたりの設定周り、使い方などは次の記事でまとめていますので、ぜひ読んでみてください。
UniTaskの便利な使い方「WhenAll」
UniTaskの超絶便利機能「WhenAll」について紹介します。WhenAllは現場で本当によく使います。WhenAllとは何かというと 「複数の処理が全て終了するまで待機する」 という機能です。
文字だけだとイメージがつきづらいと思いますので、次の動画を御覧ください。
Unity-chanが全員集まったら、全員同時にジャンプをするというサンプルです。
- 全員が集まるまで待機
- 全員でジャンプ
といった処理フローをUniTaskで実装しています。
このように「WhenAll」を使うと、 すべての処理が終了後、次の処理を始めることができる のです。ソースコードは以下のような感じです。
Character[] _charas;
private async UniTask WhenAllTest()
{
// ① UniTaskを格納する配列を作成
var tasks = new UniTask[_charas.Length];
for(var i = 0; i < _charas.Length; i++)
{
// ② UniTaskを配列に格納
tasks[i] = _charas[i].Run();
}
// ③ 配列内の全UniTaskの処理が終了するまで待機
await UniTask.WhenAll(tasks);
// ④ UniTask終了後の処理
foreach(var chara in _charas)
{
chara.Jump();
}
}
ポイントは UniTask型の配列を作ってWhenAllメソッドの引数に渡しているところ です。
すると、先の動画のような複数のUniTaskを待機する処理が実装可能になります。
現場でよく使うUniTask.WhenAllの例
ここでは現場でよく使うWhenAllの例を紹介をします。複数のロード処理が必要な場面です。
ここに画像A, B, Cを表示する画面があったとします。
つまり、画面を表示する前に画像(A, B, C)のすべてのロード完了を待機する必要があるということです。
こんな時にWhenAllは役立ちます。
private async UniTask ShowScreen()
{
// ① 画面表示の前に画像をロード
await UniTask.WhenAll(
// ② A~Cの画像をロードする処理
LoadImage("A"),
LoadImage("B"),
LoadImage("C"),
);
// ③ すべての画像をロードしたら画面表示の処理開始
InternalShowScreen();
}
// 画像ロードするメソッド
private UniTask LoadImage(string id)
{
// ~~~~ 略 ~~~~
}
このように WhenAll
を使うと 複雑な処理を数行で実現できる のです。ぜひ使いこなせるようにしておきましょう。実際の開発現場でもめっちゃ使います。
UniTaskを使う上での注意点「キャンセル処理」
UniTaskを使う上で大事な注意点があります。それは キャンセル処理 です。キャンセル処理とは 処理の中断 です。
例えば、長めの演出中に画面タップなどの ユーザー操作で演出スキップ したいことってよくあります。
コルーチンと違って UniTaskの場合GameObjectを非アクティブにしても処理は中断しません。 自分自身で 明示的に停止させる 必要があります。
具体的には CancellationToken
という中断用のトークンをUniTaskを使うたびに発行します。詳しくは次の記事にわかりやすくまとめていますので、ぜひ読んでみてください。
まとめ : UniTaskはUnity開発で必須
本記事ではUniTaskのインストールから基本的な使い方までをわかりやすく紹介してきました。
記事の内容を簡単にまとめます。
①UniTaskはUnityの開発現場では必須級のライブラリ
②UniTaskはPackage Managerを使えば簡単にインストール可能
③UniTaskはasync、awaitを使用
④UniTask.WhenAllはメチャ便利
⑤UniTaskのキャンセルには要注意
こんな感じです。
この記事だけでは正直UniTaskの魅力は10%も伝わらないかもしれません。ただ、だまされたと使って見てください。 使えば使うほどい良いライブラリ だということがわかってきます。個人的に良いなと思うポイントは 「書き味」 です。良いライブラリは書き味が違います。
ぜひ、UniTaskをいろいろ触ってみて書き味を感じてみてください。
UniTaskを使ったことがない人は、ぜひ、本記事を参考にインストールしてみてください(無料なので)。
使ってみて「良いな」って思ったら感謝の意を込めてGitHubのStarをクリックしましょう。
おそらく、オオバは今後もUniTaskを使い続けていくと思いますので、便利な使い方や落とし穴はまた別の記事で紹介していこうと思います。
この記事が気に入ったらフォローしよう
「Unity初心者大学」というUnity初心者向けのYouTube始めました!!
ぜひチャンネル登録をお願いします!
最後まで読んでいただきありがとうございました!
すばらしいUniTaskライフをお過ごしください。
- Unity2022.3.4f1
- UniTask v2.4.1