web-dev-qa-db-ja.com

Unityでは、Update()でTime.deltaTimeを引くのではなく、いつコルーチンを使用すればよいですか?

以下は、強調したい違いの簡単な例です。

コルーチンの使用:

_public float repeatRate = 5f;
void Start()
{
    StartCoroutine("RepeatSomething");
}
IEnumerator RepeatSomething()
{
    while (true)
    {
        yield return new WaitForSeconds(repeatRate);
        // Do something
    }
}
_

Update()および_Time.deltaTime_の使用:

_public float repeatRate = 5f;
private float timer = 0;
void Update()
{
    if (timer < 0)
    {
        // Do something
        timer = repeatRate;
    }
    timer -= Time.deltaTime;
}
_

どちらを使用するのか、どちらを使用するのがよいのですか?それぞれの長所/短所は何ですか?

5
Roger Wang

ほとんどの場合、答えはそうなります。

一般に、更新とコルーチンのパフォーマンスの違いは関係ありません。自分に最も適した方法に従ってください。ただし、コルーチンのような方法に従う場合は、_MEC Coroutines_ではなく、よりパフォーマンスの高い_Unity Coroutine_を使用してください。

簡単な使用法

ユニティフォーラム で述べたように、一般的に "Coroutinesは、いくつかのフレームでメソッドを実行するのに役立ちます[そして、それを忘れます]。"

そのうちのいくつか(1万未満)を使用する場合は、_Unity Coroutines_でも問題ありません。

高度な使用法

現時点では、Unityは Task/Async をサポートしていますが、パフォーマンスはまだかなり低くなっています。したがって、Coroutinesを使用してAsync機能をシミュレートすることを検討するかもしれません。

この場合、投稿した例のように、Coroutinesを使用してUpdateループをすべて(またはほとんど)削除することもできます。

Updateループを使用すると、何もしなくてもif (timer < 0)を高コストでチェックし続けるため、これは特にパフォーマンスの点で役立ちます。また、空の更新ループでもパフォーマンスの問題です。

一方、イベントが発生したときにCoroutinesを開始および停止するだけの場合もあります。また、コルーチンが停止すると、パフォーマンスコストは0になります。

この方法を使用する場合は、 MECコルーチン を使用することを強くお勧めします。これにより、Unityコルーチンによって引き起こされるすべてのパフォーマンスの問題が削除されます(同じ機能を備えています)。


結論として

  1. ほとんどの場合、このパフォーマンスの違いは関係ありません。
  2. _MEC Coroutines_は、更新ループよりも少しパフォーマンスが優れています
  3. Updateループは通常、_Unity Coroutines_よりもパフォーマンスが優れています
  4. _Unity Coroutines_は、まれにしか発生しない単純な時間指定タスクにのみ使用する必要があります

PS: この答え ユニティコルーチンについては、それらがどのように深く機能するかを理解するのに役立つかもしれません。
PPS: この古い答え はさらに洞察を与えるかもしれませんが、特にガベージコレクションについて話すときは少し古くなっています。

2
Jack Mariani

コルーチンを使用しないでください。

これにより、特にゲームエンジンで問題を解決する方法が大幅に改善され、不要なガベージの作成、ガベージコレクション、呼び出しの遅延、およびインターフェイスとコルーチンに関するその他の問題が回避されます。

また、プログラミングがより速く、よりシンプルになり、何が何をしているのか、どこで、いつ、なぜ、そしてどのように行うのかについて考えやすく、理由付けも容易になります。

コルーチンは中毒性のある薬物であり、効果がないかのように避ける必要があります。彼らはあなたのプログラムについてよりよく考え、それをよりよく書くことよりも利点がないからです。

コルーチンの使用を開始すると、コーヒーにクリームと砂糖を入れるのと少し似ています。それぞれがいくらか組み合わさると、常にそれぞれ少しずつ追加することになります。すべてが物事を強化しているようです。

風味がそれほど重要ではなくなったため、最終的にはコーヒーの品質に妥協することになります。カフェインだけでなく、乳製品、砂糖、コーヒーに夢中になっています。

飲みすぎると、簡単に下がってしまうので、レシピを習得したので簡単に味わえます。味はとても美味しいので、間違いはありません。しかし、落ち着きがなく、ストレスがかかり、よく眠れなくなります。 、脂肪の奇妙な部分があなたの体に現れ、あなたはあなたが最も愛する人々の中でいらいらするでしょう。

解決策のように見えたものが問題になりました。それから、あなたの健康と精神的健康に、本当に大きな問題が現れ始めます。

緑茶を飲むだけでコルーチンを使用しないことで、これをすべて回避できます。あなたが後で支払う価格は、コーヒー中毒になるために、それだけの価値はありません。

ずっと。

1
Confused

すべての利回りで、実際にnew WaitForSeconds()と言うように新しいオブジェクトを作成しています。ただし、違いはまだそれほど重要ではありません。一方、コルーチンは読みやすくなります。特に、同じコルーチンで異なる待機時間で複数のyieldを使用する必要がある場合を考慮してください。Updateでそのようなことを実装すると、コードがかなり乱雑になります。

1
Onurcan Onder

簡単な答えは 読みやすい方を使用する (私が知る限り、パフォーマンスに目立った違いはありません)。私は(通常)コルーチンを使用します。これは、更新ループをより整理しておくのに役立ち、通常、セットアップが少し簡単になると感じているためです(タイマー用の変数を作成する必要がないなど)。

1
Lightning_A

正直に言うと、彼らは同じタスクを実行します。どちらも1フレームごとに実行されます(あなたの場合は、最初の実行から5秒が経過したかどうかを確認します)。ただし、いくつかの重要な違いがあります。つまり、最も重要なのは実行順序です。 CoroutinesalwaysUpdate()の後に実行されます。何らかの理由でCoroutineを正しい情報で更新するために更新する必要があるUpdate()で何かが発生している場合、これは重要です。しかし、通常、これは当てはまりません。

結論として、どちらかがあなたの望ましいタスクを完了するでしょう、そしてそれは通常は好みと組織の問題に帰着します。

1
Scornz