Unityに関連する記事です

 UniTask を利用した非同期処理の実装例を学習します。

 Google の SpreadSheet(スプレッドシート。以下、GSS とします)のシートの情報を1シートにつき、1つのスクリプタブル・オブジェクトに取り込む方法について、
コルーチンにより実装していた非同期処理の部分を UniTask (async/await) を利用した処理に置き換えて実装します。

 事前にこちらの記事より、元となる処理の作成を行ってから学習をします。



<新しい学習内容>
 ・async キーワードと await キーワードを利用した非同期処理
 ・UniTask とは?
 ・CancellationToken(キャンセレーショントークン)



<async キーワードと await キーワードを利用した非同期処理>


 このキーワード群は C# の Task クラス、および UniTask クラスに紐づいた構文です。
よって Task クラスか UniTask クラスと一緒に宣言を行う必要があります。

 async(エイシンク) は Asynchoronous(エイシンクロナス) という単語の略語で「非同期」という意味です。
これは await を利用するメソッドを記述するために、メソッドの宣言時につける必要があるキーワードです。
その際、戻り値には UniTask を利用します。

<async キーワード>
private async UniTask Hoge() {

}



 await(アウェイト) キーワードは「待ち受ける」という意味です。
このキーワードは、非同期処理として実行するメソッドの先頭に記述します。

<await キーワード>
private async UniTask Hoge() {
    await HogeHoge();
}



 この2つのキーワードを利用し、戻り値の型を UniTask にすることにより、コルーチン処理と同じように非同期処理を実行し、その処理の解決を待ち受ける機能(メインスレッドに処理が戻ってくるのを待つ)を実装することが出来ます。
またコルーチンメソッド内で記述が可能であった yield return null や WaitUntil なども処理も UniTask には static メソッドとして用意されていますので、async / await キーワードを使うことで、コルーチンメソッドを置き換えることが出来ます。

 またコルーチンでは直接指定できなかった戻り値も UniTask<T> として記述できるようになっています。
タプル型を利用することで複数の戻り値を持たせることも可能です。

 なお UniTask には void に相当する UniTaskVoid 型があります。こちらの型にすることで処理を待ち受けない(await できない)メソッドとして機能させることも出来ます。
処理の完了を通知する必要がないメソッドで利用するため、この機能は UniTask を使った非同期処理の最後に利用されることになります。(非同期処理を最初に処理し始める場所、とも言えます)

<参考サイト>
MicroSoft
https://docs.microsoft.com/ja-jp/dotnet/csharp/pro...
Qiita @4_mio_11 様
非同期理解のためにasync/awaitとTaskの基礎を学んだ話
https://qiita.com/4_mio_11/items/f9b19c04509328b1e...


<UniTask をインポートする>


 以下の Github サイトから UniTask 用の Unitypackage をダウンロードしてインポートを行うか、PackageManager 経由でインポートを行います。


1.Github サイトから Unitypackage をダウンロードしてインポートする場合

https://github.com/Cysharp/UniTask/releases

<Unitypackage を選択する>



 Unity を起動し、ダウンロードした Unitypackage を Unity 内の Assets フォルダにドラッグアンドドロップしてください。
インポート用のポップアップウインドウが開きますので、Import を押してください。自動的にインポートが始まります。


2.PackageManager 経由でインポートする場合


 Unity 内で PackageManager ウインドウを開き、左上の + アイコンを押して、Add package from git URL... を選択します。





 Github の URL を入力するポップアップが出ますので、そちらに、下記の URL をコピーして貼り付け、Add ボタンを押します。

<UniTask の GitURL>
 https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask


<上記の URL をコピーして貼り付けてから Add ボタンを押す>



 以上の手順を行うと、自動的に UniTask のインポートが始まります。








<UniTask とは?>


 C# において提供されている Task 機能を、より Unity に最適化し、より扱いやすくしたものが、UniTask になります。
UniTask は非同期処理に優れており、コルーチンによる処理の多くを async / await キーワードを使って非同期処理として記述できるようになります。

Chsharp 様
https://github.com/Cysharp/UniTask


 スクリプト内で UniTask の機能を利用する場合には、using Cysharp.Threading.Tasks; の宣言が必要になります。

 大きな違いとして、コルーチンや Invoke メソッドは MonoBehavior クラス内のメンバであるため、MonoBehavior を継承しないと実装が出来ませんが、UniTask と async / await にはその制約はありません。つまり、MonoBehavior を継承していない static クラスなどでも利用可能です。
 
 また、コルーチンの処理はゲームオブジェクトが破棄された段階で自動的に処理が破棄(キャンセル)されますが、
async / await で実装した非同期処理は自動的には停止しませんので、キャンセル処理を考えて実装する必要があります。


<参考サイト>
Qiita @toRisouP 様
UniTask機能紹介
https://qiita.com/toRisouP/items/4445b6b9bf00e49eb...
ソフトメディア研究会 すいま 様
UniTaskでレッツ非同期!
http://softmedia.sakura.ne.jp/advent-calendar/2019...


スプレッドシートを読み込んでスクリプタブル・オブジェクトに取り込むための処理を修正する


 GSSReader クラスと GSSReciver の2つのクラスのリファクタリングを行い、
非同期処理の部分をコルーチンメソッドから UniTask の機能と async / await の機能を利用した処理に修正します。

 リファクタリングになりますので、修正後は同じように動作することが求められます。


GSSReader スクリプトを修正する


 スプレッドシートにアクセスし、シート内の情報をシートごとに取得しておくためにクラスです。


GSSReader.cs

 <= クリックすると開きます



<CancellationToken(キャンセレーショントークン)>


 非同期処理の途中で処理が停止するような事態が発生した場合についての制御の処理です。

 コルーチンメソッドの処理については、ゲームオブジェクトの生存状態とコルーチンメソッドの処理が紐づいて動いていますので、
ゲームオブジェクトが破壊されると、その時点でコルーチンメソッドの処理も自動的に終了します。

 UniTask で利用する async / await による非同期処理はゲームオブジェクトに処理が紐づいていないため、
処理を実行したスクリプトがアタッチされているゲームオブジェクトが破壊されても、処理自体は動き続けてしまうことになり、
メモリリークを引き起こす原因となります。

 そのため、事前に処理を停止するための制御を用意しておいて、処理の停止を行えるようにしておく必要があります。



 C# には CancellationToken という機能が用意されておりますが、UniTask でも同様の機能が用意されています。
これを利用することで非同期処理を停止させることが出来るようになります。

 C# の CancellationToken は System.Threading の namespace に用意されていますが、
UniTask の宣言内にも用意されていますので、重複して宣言する必要はありません。


 using Cysharp.Threading.Tasks;

 // CancellationToken の作成
 var token = this.GetCancellationTokenOnDestroy();

 // 非同期処理に CancellationToken の設定を行い、非同期処理をキャンセルした場合には処理が停止するようにセットする
  await request.SendWebRequest().WithCancellation(token);



GSSReceiver スクリプトを修正する


 スプレッドシートから取得したデータが GSSReacer クラスの SheetData 配列変数内に格納されているので、
それをシート単位で任意のスクリプタブル・オブジェクトに値として取り込むためのクラスです。


GSSReceiver.cs

 <= クリックすると開きます



ゲームを実行して動作を確認する


 非同期処理をコルーチンメソッドから UniTask を利用した処理にリファクタリングしただけですので、
ゲームを実行した際の処理はいままでと同じように動作することを確認します。

 ゲームを実行すると、自動的にスプレッドシートの読み込みと、読み込んだ情報をスクリプタブル・オブジェクトに取り込む処理が実行されます。

 SkillDataSO スクリプタブル・オブジェクトを確認し、Size が 0 ではなく、スプレッドシートの行の数分になっており、値が代入されているかを確認してください。

 また複数のスクリプタブル・オブジェクトを用意している場合も同様に確認してください。





 以上になります。

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu



プログラムの基礎学習

コード練習

技術/知識(実装例)

2Dおはじきゲーム(発展編)

2D強制横スクロールアクション(発展編)

3Dダイビングアクション(発展編)

2Dタップシューティング(拡張編)

レースゲーム(抜粋)

2D放置ゲーム(発展編)

3D脱出ゲーム(抜粋)

2Dリアルタイムストラテジー

2Dトップビューアドベンチャー(宴アセット使用)

3Dタップアクション(NavMeshAgent 使用)

2Dトップビューアクション(カエルの為に〜、ボコスカウォーズ風)

3Dトップビューアクション(白猫風)

VideoPlayer イベント連動の実装例

VideoPlayer リスト内からムービー再生の実装例(発展)

AR 画像付きオブジェクト生成の実装例

AR リスト内から生成の実装例(発展)

private



このサイト内の作品はユニティちゃんライセンス条項の元に提供されています。

管理人/副管理人のみ編集できます