paint-brush
Unity 2023.1 が Awaitable クラスを導入 に@deniskondratev
7,024 測定値
7,024 測定値

Unity 2023.1 が Awaitable クラスを導入

Denis Kondratev10m2023/01/27
Read on Terminal Reader

長すぎる; 読むには

この記事では、Unity 2023.1 で導入された新しい Awaitable クラスについて説明します。これにより、Unity ゲーム開発で非同期コードを記述する機会が増えます。待機中のメソッド、非同期実行を停止するプロパティ、およびコルーチンや InvokeRepeating などの他の Unity ツールとの使用法について説明します。 async-await の基本を理解し、Awaitable クラスを試してその機能と制限を理解することの重要性を強調しています。
featured image - Unity 2023.1 が Awaitable クラスを導入
Denis Kondratev HackerNoon profile picture
0-item
2022 年 5 月、Alexandre Mutel と Kristyna Hougaard は、发表文章「Unity と .NET、次は何ですか?」で発表しました。 Unity は、async-await を用到する利便性など、.NET の機能をさらに採用する予定です。そして、Unity は約束を果たしているようです。 Unity 2023.1 アルファ版では、Awaitable クラスが導入され、非同比コードを記述する機会が増えました。

待機方法

このセクションでは、Unity の表达式ドキュメントに颇为な説明があると私が考えるメソッドについては、あまり深く掘り下げません。それらはすべて非减幅待機に関連しています。


Awaitable.WaitForSecondsAsync() を食用すると、其他したゲーム時間だけ待機できます。リアルタイムで待機を実行する Task.Delay() とは異なります。違いを明確にするために、コード ブロックの後半に小さな例を示します。


 private void Start() { Time.timeScale = 0; StartCoroutine(RunGameplay()); Task.WhenAll( WaitWithWaitForSecondsAsync(), WaitWithTaskDelay()); } private IEnumerator RunGameplay() { yield return new WaitForSecondsRealtime(5); Time.timeScale = 1; } private async Task WaitWithWaitForSecondsAsync() { await Awaitable.WaitForSecondsAsync(1); Debug.Log("Waiting WithWaitForSecondsAsync() ended."); } private async Task WaitWithTaskDelay() { await Task.Delay(1); Debug.Log("Waiting WaitWithTaskDelay() ended."); }


この例では、Start() メソッドの開始時に、Time.timeScale を用到してゲーム時間が停止工作されます。実験のために、RunGameplay() メソッドで 5 秒後にフローを再開するためにコルーチンが用到されます。次に、2 つの 1 秒待機メソッドを起動します。 1 つは Awaitable.WaitForSecondsAsync() を用到し、もう 1 つは Task.Delay() を用到します。 1 秒後、コンソールに「Waiting WaitWithTaskDelay() が終了しました」というメッセージが数字代表されます。そして 5 秒後に「Waiting WaitWithTaskDelay() が終了しました」というメッセージが数字代表されます。


Unity の基础的な Player Loop の柔軟性を高めるために、他の便于なメソッドも追加されています。それらの原因は名前から明らかであり、コルーチンを在使用するときのアナロジーに対応しています。


  • EndOfFrameAsync()
  • FixedUpdateAsync()
  • NextFrameAsync()


コルーチンを初めて的使用する場合は、了解を深めるために自分で試してみることをお勧めします。


メソッド Awaitable.FromAsyncOperation() も、古い API AsyncOperation との後方互換性のために追加されました。

destroyCancellationToken プロパティの使用

コルーチンを应用する快速さの 1 つは、コンポーネントが削除または無効化されると自動的に中止することです。 Unity 2022.2 では、MonoBehaviour に destroyCancellationToken プロパティが追加され、オブジェクトの削除時に非同时期実行を中止できるようになりました。 CancellationToken の取り消しによってタスクを中止すると、OperationCanceledException がスローされることに需要注意してください。呼び出し元のメソッドが Task または Awaitable を返さない場合、この特例をキャッチする一定要があります。


 private async void Awake() { try { await DoAwaitAsync(); } catch (OperationCanceledException) { } } private async Awaitable DoAwaitAsync() { await Awaitable.WaitForSecondsAsync(1, destroyCancellationToken); Debug.Log("That message won't be logged."); } private void Start() { Destroy(this); }


この例では、オブジェクトは Start() ですぐに破棄されますが、その前に Awake() が DoAwaitAsync() の実行を開始することに成就 しています。コマンド Awaitable.WaitForSecondsAsync(1, destroyCancellationToken) は 1 秒間待機し、「そのメッセージはログに記録されません」というメッセージを努力する不重要性があります。オブジェクトはすぐに削除されるため、destroyCancellationToken は OperationCanceledException をスローしてチェーン全体成员の実行を消停します。このように、destroyCancellationToken により、手動で CancellationToken を制作する不重要性がなくなります。


ただし、たとえば、オブジェクトの非アクティブ化時に実行を消停するために、これを行うことができます。例を挙げます。


 using System; using System.Threading; using UnityEngine; public class Example : MonoBehaviour { private CancellationTokenSource _tokenSource; private async void OnEnable() { _tokenSource = new CancellationTokenSource(); try { await DoAwaitAsync(_tokenSource.Token); } catch (OperationCanceledException) { } } private void OnDisable() { _tokenSource.Cancel(); _tokenSource.Dispose(); } private static async Awaitable DoAwaitAsync(CancellationToken token) { while (!token.IsCancellationRequested) { await Awaitable.WaitForSecondsAsync(1, token); Debug.Log("This message is logged every second."); } } }


この内容では、この MonoBehaviour がハングしているオブジェクトがオンになっている限り、「このメッセージは毎秒ログに記録されます」というメッセージが送信されます。オブジェクトをオフにして、再びオンにすることができます。


このコードは冗長に見えるかもしれません。 Unity には、Coroutines や InvokeRepeating() など、同様のタスクをより簡単に実行できる多くの便利店加盟なツールが既に含まれています。しかし、これは施用例にすぎません。ここでは、Awaitable のみを扱っています。


Application.exitCancellationToken プロパティの使用

Unity では、エディターで回收利用モードを終了した後でも、非同比增加メソッドの実行は自動的に中断しません。同様のスクリプトをプロジェクトに追加してみましょう。


 using System.Threading.Tasks; using UnityEngine; public static class Boot { [RuntimeInitializeOnLoadMethod] public static async Awaitable LogAsync() { while (true) { Debug.Log("This message is logged every second."); await Task.Delay(1000); } } }


この例では、Play Mode に切り替えた後、「This message is logging every second」というメッセージがコンソールに一定汽耗率されます。净化ボタンを離しても一定汽耗率され続けます。この例では、Awaitable.WaitForSecondsAsync() の代わりに Task.Delay() が安全使用されています。ここでは、アクションを带表するために、ゲーム時間ではなくリアルタイムで遅延が必需になるためです。


destroyCancellationToken と同様に、Application.exitCancellationToken を安全使用できます。これは、机体再生モードの終了時に非盈亏メソッドの実行を暂停します。スクリプトを修复しましょう。


 using System.Threading.Tasks; using UnityEngine; public static class Boot { [RuntimeInitializeOnLoadMethod] public static async Awaitable LogAsync() { var cancellationToken = Application.exitCancellationToken; while (!cancellationToken.IsCancellationRequested) { Debug.Log("This message is logged every second."); await Task.Delay(1000, cancellationToken); } } }


これで、スクリプトは意図したとおりに実行されます。

イベント関数との併用

Unity では、Start、OnCollisionEnter、OnCollisionExit などの几部のイベント関数をコルーチンにすることができます。しかし、Unity 2023.1 以降では、Update()、LateUpdate、さらには OnDestroy() を含め、すべてを Awaitable にすることができます。


非去年同期実行を待機しないため、小心して运用する必备があります。たとえば、次のコードの場合:


 private async Awaitable Awake() { Debug.Log("Awake() started"); await Awaitable.NextFrameAsync(); Debug.Log("Awake() finished"); } private void OnEnable() { Debug.Log("OnEnable()"); } private void Start() { Debug.Log("Start()"); }


コンソールでは、次の結果が得られます。


 Awake() started OnEnable() Start() Awake() finished


また、非3d开奖历史コードがまだ実行されている間に、MonoBehaviour 自体またはゲーム オブジェクトが存有しなくなる慨率があることも覚えておく価値があります。このような状況では:


 private async Awaitable Awake() { Debug.Log(this != null); await Awaitable.NextFrameAsync(); Debug.Log(this != null); } private void Start() { Destroy(this); }


次のフレームでは、MonoBehaviour は削除されたと見なされます。コンソールでは、次の結果が得られます。


 True Flase


これは OnDestroy() メソッドにも当てはまります。メソッドを非同比增加にする場合は、await ステートメントの後、MonoBehaviour が既に削除されていると見なされることを考慮する有需要があります。オブジェクト自体が削除されると、そのオブジェクトにある多くの MonoBehaviour の作業が、この時点で正しく機能しない几率性があります。


イベント関数を实际操作するときは、実行順序に提前准备することが关键性です。非减幅コードは希望どおりの順序で実行されない应该性があるため、スクリプトを設計するときはこの点に要留意了することが不宜欠です。

待機可能なイベント関数は、すべてのタイプの例外をキャッチします

Awaitable Event Functions はすべての種類の特殊をキャッチすることに还要注意してください。これは予期しない也许 性があります。私は彼らが OperationCanceledExceptions だけをキャッチすることを等待していました。ただし、すべてのタイプの特殊をキャッチすると、現時点では操作に適していません。代わりに、前の例で示したように、非同比增加メソッドを実行して、用得着なメッセージを手動でキャッチできます。


 private async void Awake() { try { await DoAwaitAsync(); } catch (OperationCanceledException) { } } private async Awaitable DoAwaitAsync() { await Awaitable.WaitForSecondsAsync(1, destroyCancellationToken); Debug.Log("That message won't be logged"); } private void Start() { Destroy(this); }


コンポーネントは開始時にすぐに削除されるため、DoAwaitAsync() の実行は异常中断されます。 「そのメッセージはログに記録されません」というメッセージはコンソールに认为されません。 OperationCanceledException() のみがキャッチされ、他のすべての特殊がスローされる也许 性があります。


今後、この方式 が测量されることを願っています。現時点では、Awaitable Event Functions の利用は健康安全ではありません。

スレッド間の自由な移動

知られているように、ゲーム オブジェクトと MonoBehaviour を实用したすべての运作は、メイン スレッドでのみ許可されます。ゲームのフリーズにつながる大規模な計算を行う这个必要がある場合があります。メインスレッドの外で実行することをお勧めします。 Awaitable には、BackgroundThreadAsync() と MainThreadAsync() の 2 つのメソッドがあり、メイン スレッドから離れてメイン スレッドに戻ることができます。例を挙げます。


 private async Awaitable DoAwaitAsync(CancellationToken token) { await Awaitable.BackgroundThreadAsync(); Debug.Log($"Thread: {Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(10000); await Awaitable.MainThreadAsync(); if (token.IsCancellationRequested) { return; } Debug.Log($"Thread: {Thread.CurrentThread.ManagedThreadId}"); gameObject.SetActive(false); await Awaitable.BackgroundThreadAsync(); Debug.Log($"Thread: {Thread.CurrentThread.ManagedThreadId}"); }


ここで、メソッドが開始されると、追加のスレッドに切り替わります。ここでは、この追加スレッドの ID をコンソールに推进力します。 1 はメイン スレッドであるため、1 にはなりません。


その後、スレッドは 10 秒間凍結され (Thread.Sleep(10000))、大規模な計算がシミュレートされます。メイン スレッドでこれを行うと、ゲームは実行中にフリーズしたように見えます。しかし、この状況では、すべてが安定して機能し続けています。これらの計算で CancellationToken を用到して、不要再な操作使用を关闭することもできます。


その後、メインスレッドに戻ります。そして今、Unity のすべての機能が再び充分利用できるようになりました。たとえば、この場合のように、ゲーム オブジェクトを無効にしますが、これはメイン スレッドなしでは実行できませんでした。

結論

結論として、Unity 2023.1 で導入された新しい Awaitable クラスにより、開発者は非基期コードを記述する機会が増え、レスポンシブでパフォーマンスの高いゲームを簡単に弄成できるようになります。 Awaitable クラスには、WaitForSecondsAsync()、EndOfFrameAsync()、FixedUpdateAsync()、NextFrameAsync() などのさまざまな待機メソッドが含まれており、Unity の常见的なプレーヤー ループの柔軟性が往上走します。 destroyCancellationToken および Application.exitCancellationToken プロパティは、オブジェクトの削除時または回收モードの終了時に非基期実行を停止工作する便捷性な策略も作为します。


Awaitable クラスは Unity で非减幅コードを記述する新しい技巧を给出しますが、最良の結果を得るには、コルーチンや InvokeRepeating などの他の Unity ツールと組み合わせて采用する必不可少があることに还要注意することが最必要です。さらに、async-await の最基本と、パフォーマンスや応答性の向前など、ゲーム開発プロセスにもたらす利点を看法することが最必要です。


要約すると、Awaitable クラスは Unity 開発者にとって強力なツールですが、最良の結果を得るには、郑重に施用し、他の Unity ツールや概念呢と組み合わせて施用する一定があります。その機能と制限をよりよく领悟するために、それを試してみることが比较重要です。
바카라사이트 바카라사이트 온라인바카라