yield返回new WaitForSeconds(2)破坏函数

时间:2012-10-24 09:51:00

标签: c# unity3d yield-return

我决定创建一个像游戏一样的小记忆,用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所需的东西,那么一切正常(除了玩家看不到第二张牌,因为它会立即翻回)。

我的收益率有什么问题?

3 个答案:

答案 0 :(得分:5)

您需要使用StartCoroutine启动协程:

StartCoroutine(FlipCardFaceUp(card));

正如Marc Gravell所说,需要枚举一个迭代器块来做任何事情,这就是StartCoroutine所做的事情(异步,也可能是团结所需的其他东西)。 “异步”部分也是在Coroutine完成之前立即打印"Returned from FlipCard"的原因。

如果您想在打印"Return from FlipCard"之前等待Coroutine完成,您也可以使用yield

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

请注意,您无法在yieldUpdate内使用FixedUpdate

编辑:看到你试图在OnGUI方法中执行此操作,更好的方法可能是使用Card类型的变量,以便您可以记住要翻转的卡片。然后,在Update中,您可以检查该变量,如果它表示需要翻转卡片,则可以启动协程。

答案 1 :(得分:3)

通过添加yield return,您已将其设为迭代器块。迭代器块仅在迭代时执行 - 它们演示“延迟执行”。因此,要实现此功能,您需要使用返回的枚举。最简单的是,这可能是:

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

然而,可能还有一些其他方式,团结希望将其作为一个共同例程更新来消费;看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;
}

答案 2 :(得分:0)

如果您通过yield return new WaitForSeconds(2)调用方法,则只能使用StartCoroutine。您的第一个代码块将立即返回,但Unity3d将负责运行您的方法的其余部分(包括2秒等待并在之后继续)。