13

このメソッド(Unity C#スクリプト内)を取得しましたが、「yield」部分が実際にどのように機能するのかわかりません。

MSDNから、関数がIEnumeratorを返すことはわかっていますが、このコードは1.5秒待機し、反復されません。これは、内部で作成されたオブジェクトが複数回作成されたことを意味するためです。このコードがどのように機能するかを私に説明できる人はいますか?

IEnumerator DestroyShip()
{
    // create new gameobject
    Instantiate(ExplosionPrefab, transform.position, transform.rotation);
    // make current gameobject invisible
    gameObject.renderer.enabled = false;
    // set new position for the current gameobject
    transform.position = new Vector3(0f, transform.position.y, transform.position.z);
    // wait for 1,5 seconds 
    yield return new WaitForSeconds(1.5f);
    // make the current gameobject visible again
    gameObject.renderer.enabled = true;
}
4

3 に答える 3

27

コンパイラが生成する Enumerator が繰り返されています。一度。

コンパイラは、MoveNext() 関数と Current プロパティを持つ IEnumerator を実装するクラスを生成します。クラスには、呼び出し間の関数の状態を保存するために必要なすべてのメンバーが含まれます。正確な詳細は「コンパイラの魔法」と見なすことができます。

この生成されたクラスのオブジェクトは、Unity3d エンジンによって処理および管理されます。Unity3d エンジンは、フレームごとに 1 回、アクティブな各コルーチンで MoveNext() を呼び出します (特に指示がない限り)。

これにより、Unity3d プログラマーは、一度に 1 フレームずつ再生されるスクリプトを作成できるようになりました。C# コンパイラの魔法と Unity3d エンジンの魔法を組み合わせることで、非常に強力でありながら使いやすいスクリプティングが実現します。

あなたの質問に答えるには: 関数内のコードは 1 回実行されますが、'yield return' ステートメントで一時停止します。

前述のように、IEnumerator を実装する特別なオブジェクトが C# コンパイラによって作成されます。

MoveNext() への最初の呼び出しで、関数はエクスプロージョンを作成し、現在のオブジェクトを「new WaitForSeconds(1.5f)」に設定します。

Unity3d エンジンはこのオブジェクトを検査し、それが特別なクラス「WaitForSeconds」のインスタンスであることを確認して、列挙子を待機キューに置き、1.5 秒が経過するまで 2 番目の要素を要求しません。その間、多くのフレームがレンダリングされ、爆発が再生されます。

1.5 秒後、Unity はキューから列挙子を取得し、MoveNext() を再度呼び出します。関数の 2 番目の部分はすぐに実行されますが、2 番目のオブジェクトの生成に失敗します。MoveNext() は false を返して、新しい要素の取得に失敗したことを示します。これは、この列挙子を破棄するよう Unity3d に通知する信号です。ガベージ コレクターは、ある時点でメモリを再利用します。

前述のとおり、多くのコンパイラと Unity3d マジックが進行中です。関数が各 yield return ステートメントで次のフレームまで保留されることを覚えている限り、これらの特別な関数から十分な恩恵を受けることができます。

于 2010-08-09T09:54:20.163 に答える
4

を1yield回使用すると、1 つの要素を含む IEnumerator を返すかのようになります。そのため、反復しないという印象を受けます。

これは、yield キーワードのかなり奇妙な使い方です。コンテキスト全体を見ないと、なぜこのように実装されたのかを理解するのは困難です。

于 2010-08-09T09:22:43.530 に答える
1

より柔軟で使いやすいとIEnumerableいうよりも、戻ったほうがよいでしょう。IEnumeratorを使用するとさらに良いIEnumerable<T>です。Yield return は、反復子ブロックを実装するための単なる構文糖衣です。コンパイラーは、プログラムで簡単に生成できる基本的に標準のボイラープレートであるため、関連するコードを生成します。一般に、一連の単一アクションをコレクションのように見せたい場合は、yield return を使用します。たとえば、次のようになります。

public IEnumerable<Thing> GetThings()
{
    yield return GetNextThing();
}
于 2010-08-09T09:27:03.833 に答える