2

我决定创建一个像游戏一样的小记忆,用unity3d学习游戏开发。
游戏应在玩家点击卡片后等待 2 秒,然后再将卡片翻转回来。
-statementyield 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一切正常(除了玩家看不到第二张牌,因为它会立即翻转回来)。

我的收益回报有什么问题?

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");

请注意,您不能使用yieldfrom inside Updateor FixedUpdate

编辑:看到您正在尝试在该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 回答