2013-06-06 5 views
16

coroutines(Unity3Dなどの場合)がどのように機能するのか混乱して不思議です。コルーチンは新しいスレッドですか?ユニティのdocumentationは、彼らは言った:coroutineはUnity3Dの新しいスレッドですか?

コルーチンが与えられたYieldInstructionが終了するまでその実行(歩留まり)を一時停止することができる機能です。

そして、彼らは、C#の例hereを持っている:コルーチンであるライン、上記の例では

  1. using UnityEngine; 
    using System.Collections; 
    
    public class example : MonoBehaviour { 
        void Start() { 
         print("Starting " + Time.time); 
         StartCoroutine(WaitAndPrint(2.0F)); 
         print("Before WaitAndPrint Finishes " + Time.time); 
        } 
        IEnumerator WaitAndPrint(float waitTime) { 
         yield return new WaitForSeconds(waitTime); 
         print("WaitAndPrint " + Time.time); 
        } 
    } 
    

    私は、この例について多くの質問がありますか? WaitAndPrint()はコルーチンですか? WaitForSeconds()はコルーチンですか?

  2. この行にはyield return new WaitForSeconds(waitTime);という理由で、yieldreturnの両方が存在するのはなぜですか?私はUnity documentationで "yieldステートメントは次回の呼び出し時にyieldステートメントの後の行から関数が確実に継続することを保証する特別なリターンです"と読みました。 yieldが特別なreturnの場合、ここでreturnは何をしていますか?

  3. なぜIEnumeratorを返さなければならないのですか?

  4. StartCoroutineは新しいスレッドを開始しますか?

  5. 上記の例で何回WaitAndPrint()が呼び出されましたか? yield return new WaitForSeconds(waitTime);は本当に返されましたか?はいの場合は、上記のコードでWaitAndPrint()が2回呼び出されたと思います。そして、私はStartCoroutine()WaitAndPrint()を何度も呼び出していたと思います。しかし、私はanother Unity documentationを見ました: "コルーチンの実行は、いつでもyield文を使って中断できます。yield returnの値はコルーチンがいつ再開されるかを指定します。"これらの言葉は、私には、WaitAndPrint()が実際に返されていないと感じさせます。単に一時停止しただけだった。 WaitForSeconds()が戻るのを待っていました。この場合、上記のコードではWaitAndPrint()が一度だけ呼び出され、StartCoroutineは関数の起動に責任があり、複数回は呼び出されませんでした。

+0

タイトルの質問に答えて、コルーチン**は新しいスレッドを開始しません。スレッド自体には接続しません。 Unity3Dは基本的にフレームベースであることを忘れないでください。MonoBehavioursはフレームベースのコンセプトです。 Coroutines - Unityでは - 本質的にこのパラダイムに関連しています。スレッドはまったく関心がありません。 – Fattie

+0

私はこのチュートリアルhttp://www.unitygeek.com/coroutines-in-unity3d/にぶつかって、unity3dでコルーチンの使用について非常によく説明しています –

答えて

16

コルーチンは.net4.5ではなく、以前のバージョン(C#の> = V2.0)に非同期/のawaitがサポートする機能の種類をエミュレートするために使用される非常に強力な技術です。

Microsoft CCR(読んでください)もこのアプローチを採用しています。

1つのことを途中で止めましょう。 yieldのみが無効で、常にreturnまたはbreakが続きます。

(フロー制御メッセージを生成しない)標準のIEnumeratorについて考えてみましょう。

IEnumerator YieldMeSomeStuff() 
{ 
    yield "hello"; 
    Console.WriteLine("foo!"); 
    yield "world"; 
} 

今:

IEnumerator e = YieldMeSomeStuff(); 
while(e.MoveNext()) 
{ 
    Console.WriteLine(e.Current); 
} 

出力は何ですか?

 
hello 
foo! 
world 

列挙子は、いくつかのコードは列挙子の中走った「世界」をもたらした前に、我々は、MoveNextと呼ばれる方法が、二度目に注意してください。つまり、列挙子では、yield returnステートメントに達するまで実行されるコードを書くことができ、誰かがMoveNextを呼び出すまで一時停止します(すべての状態変数がうまくキャプチャされているので、中止したところから手に入れることができます)。 MoveNext呼び出し後、yield returnステートメントの次のビットは、yield returnに達するまで実行されます。これで、yield returnステートメントとMoveNextのEnumerator呼び出しの間でコードの実行を制御できるようになりました。

は今、私たちの列挙子は、「あなたは再びMoveNextを呼び出す前にX(WAITTIME)秒間ブラブラしてください」MoveNextの呼び出し元にというメッセージを得た代わりに文字列を与えると言います。発信者は、さまざまなメッセージを「理解する」ために書かれています。これらのメッセージは常にの行に沿って表示されます。「MoveNextをもう一度呼び出す前に起こるのを待ってください」

ここでは、コルーチンなしで非同期処理を行うなど、別の方法にその機能を書き込まなくても、処理を続ける前に他の条件を満たしている必要があるコードを一時停止して再起動する強力な手段があります。コルーチンなしでは、恐ろしい非同期状態オブジェクトを回避する必要があります。手動でアセンブルして、あるメソッドの終了から非同期の後に別のメソッドを開始する必要があります。コルーチンはスコープが(コンパイラマジックによって)保存されるので、ローカル変数が長期間存続する非同期のものにとどまるため、これを排除します。

StartCoroutineは、単にプロセス全体を開始します。列挙子でMoveNextが呼び出されます。一部のコードが列挙子で実行されます。列挙子は、MoveNextを再度呼び出すときにStartCoroutineにコードを通知する制御メッセージを生成します。これは新しいスレッドでは発生する必要はありませんが、異なるスレッドからMoveNextを呼び出して作業がどこで行われるかを制御できるため、マルチスレッドのシナリオでは便利です。

+2

そして他の人には[Unityの実行命令ページ](http:// docs .unity3d.com/Documentation/Manual/ExecutionOrder.html)は、Update()の後に実行されているコルーチンを示しています。 – Jerdak

関連する問題