Unityでコルーチンの代わりにAsync&Awaitを使用する必要がありますか?

Aug 18 2020

UnityでAsync&Awaitを使用する必要がありますか?または、コルーチンを使い続ける必要がありますか?Async&Awaitを使用する必要がある場合、コルーチンに匹敵する方法で使用するにはどうすればよいですか?

回答

2 Kevin Aug 19 2020 at 01:04

Evorlorの回答とは対照的に、コルーチンを使用する理由は次のとおりです。

  • それらは長年Unityの標準ソリューションであり、チームに参加する他の誰もがすでにそれらに慣れているはずです。
  • 彼らはエンジンと歩調を合わせています。WaitForFixedUpdate()コルーチンの次のステップが固定更新サイクル中に実行されることを保証します。WaitForEndOfFrame()次のステップが更新サイクルで実行されることを保証します。C#のasync / awaitを使用する場合、コードがエンジンと歩調を合わせていることを確認するのが複雑であることを確認する方法ありません(コメントを参照)。
  • 同様にWaitForSeconds()、電流Time.timeScaleを考慮に入れawaitます。これは、では不可能です。
  • コルーチンを実行しているオブジェクトが破棄または無効化されると、コルーチンは自動的に停止します(これは望ましくない場合があり、その場合は非同期/待機が必要になることがあります)。

別の注意:Evorlorは、状態を待つためにこの解決策を提案しました:

//Wait until condition has been met
while (!ConditionMet())
{
    yield return new WaitForEndOfFrame();
    Debug.Log("Condition has been met.");
}

これは一般的ですが、状態を待つための意図された解決策ではありません。目的のソリューションの定型文は少なくなります(場合によってはCPUオーバーヘッドも少なくなります)。

yield return new WaitUntil(() => ConditionMet());

コルーチンを使用すべきでないのはいつですか?

  • コルーチンのような関数で値を返したい場合(を参照) http://www.stevevermeulen.com/index.php/2017/09/using-async-await-in-unity3d-2017/ DMGregoryが推奨)
  • コルーチンでエラー処理を機能させるのに問題がある場合(前の箇条書きのブログ投稿を参照してください。ブロックに「yield」命令が含まれていない限り、try-catchブロックをコルーチンに入れることができます) 。
  • アプリケーションのプロファイルを作成し、コルーチンがパフォーマンスのオーバーヘッドを犠牲にしていて、それを惜しまないことがわかった場合、コルーチンを最適化してもこれを修正することはできません(ほとんどのゲームではあり得ない)
  • 拡張されない通常のC#クラスからコルーチンのような関数を実行する必要がある場合 MonoBehaviour
  • GameObjectが破棄または無効化されたときに実行を継続するために、コルーチンのような関数が必要な場合。
  • 頻繁に使用するライブラリasync(Google Firebaseなど)を使用する場合
  • コードを並列(マルチスレッド)にする必要がある場合。高価な操作を複数のフレームに分散することでパフォーマンスを向上させるために使用できますが、https://support.unity3d.com/hc/en-us/articles/208707516-Why-should-I-use-Threads-instead-of-Coroutines-。パフォーマンスを最大化するためにマルチスレッドコードが必要な場合は、C#スレッドまたはUnityジョブシステムを使用してください。
  • コルーチンを使用しない他の正当な理由がある場合

私の経験では、これらの例外はすべて非常にまれであり、通常はそれらを考慮する必要はありません。プロジェクトとコーディングスタイルに応じたYMMV。