2

unity3d でゲーム開発を学ぶために、ゲームのような小さなメモリを作成することにしました。
プレイヤーがカードをクリックしてからカードを裏返すまで、ゲームは 2 秒待機する必要があります。
-yield return new WaitForSeconds(2)ステートメントはこれに最適なはずですが、関数の行が実行されないという効果があります。

これが私のコードです:

これにより、カード グリッド (ボタン付き) が構築され、カードがクリックされたときにカードを裏返す関数が呼び出されます。

Card card = grid[i, j];

if (GUILayout.Button(new GUIContent((Texture) Resources.Load(card.getImg()), ""), GUILayout.Width(cardWidth))) {
  Debug.Log("Call FlipCard");
  FlipCardFaceUp(card);
  Debug.Log("Returned from FlipCard");
}

これはフリップ関数です。

System.Collections.IEnumerable FlipCardFaceUp(Card card) {
    Debug.Log("This isn't shown in the console");
    card.isFaceUp = true;

    if (!cardsFlipped.Contains(card)) {
        cardsFlipped.Add(card);

        if (cardsFlipped.Count >= 2) {
            playerCanClick = false;
            //Waiting 2 seconds before the cards are flipped back or are removed
            yield return new WaitForSeconds(2);

            if (cardsFlipped[0].id == cardsFlipped[1].id) {
                cardsFlipped[0].isMatched = true;
                cardsFlipped[1].isMatched = true;
            } else {
                cardsFlipped[0].isFaceUp = false;
                cardsFlipped[1].isFaceUp = false;
            }

            cardsFlipped.Clear();
            playerCanClick = true;
        } 
    }
}

これは、ゲームをテストしてカードをクリックしたときのコンソール出力です。

Call FlipCard
Returned from FlipCard

に必要なものを削除すると、yield returnすべて正常に動作します (ただし、2 枚目のカードはすぐに裏返されるため、プレイヤーは見ることができません)。

イールドリターンの何が問題になっていますか?

4

3 に答える 3

5

以下を使用してコルーチンを開始する必要がありますStartCoroutine

StartCoroutine(FlipCardFaceUp(card));

Marc Gravell が言ったように、何かを行うにはイテレータ ブロックを列挙する必要がありますStartCoroutine。「非同期」部分は"Returned from FlipCard"、コルーチンが終了する直前に出力される理由でもあります。

印刷する前にコルーチンが終了するのを待ちたい場合は、 も"Return from FlipCard"使用できます。yield

Debug.Log("Call FlipCard");
yield return StartCoroutine(FlipCardFaceUp(card));
Debug.Log("Returned from FlipCard");

またはyield内からは使用できないことに注意してください。UpdateFixedUpdate

編集:メソッドでこれを行おうとしているのを見て、どのカードを反転するかを思い出せるように、そこでOnGUIタイプの変数を使用する方が良いかもしれません。Card次に、 でUpdateその変数を確認し、カードを反転する必要があると示されている場合は、コルーチンを開始できます。

于 2012-10-24T09:57:11.283 に答える
3

を追加するyield returnことで、イテレータブロックになりました。イテレータブロックは、反復された場合にのみ実行されます。つまり、「遅延実行」を示します。したがって、これが機能するには、返された列挙を消費する必要があります。最も単純な場合、これは次のようになります。

foreach(var obj in FlipCardFaceUp(card)) {}

ただし、Unityがこれがコルーチン更新として消費されることを期待する他の方法があるかもしれません:確かに; Botz3000の回答を参照してください。ほとんどのUIでは、更新コードでのブロックは悪いです(描画を妨げます)が、統一された知識がなければ、正しい実装についてアドバイスすることはできません。私が知っている限りでは、呼び出し元のコードをイテレータブロックに変換する必要があるかもしれません。

// the following is COMPLETE GUESSWORK - I've never coded unity
// update: wrong: see Botz3000's answer, and `StartCoroutine`
Card card = grid[i, j];

if (GUILayout.Button(new GUIContent((Texture) Resources.Load(card.getImg()), ""), GUILayout.Width(cardWidth))) {
  foreach(var step in FlipCardFaceUp(card)) yield return step;
}
于 2012-10-24T09:55:03.887 に答える
0

yield return new WaitForSeconds(2)を介してメソッドを呼び出す場合にのみ使用できますStartCoroutine。コードの最初のブロックはすぐに返されますが、Unity3d がメソッドの残りの部分を実行します (2 秒間の待機とその後の継続を含む)。

于 2012-10-24T10:01:03.640 に答える