Nano Hash - криптовалюты, майнинг, программирование

yield return новая функция WaitForSeconds(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, работает все нормально (разве что вторую карту игрок не видит, т.к. она тут же переворачивается).

Что не так с моей доходностью?

24.10.2012

  • +1 Я очень люблю драматические названия. 24.10.2012

Ответы:


1

Вам нужно запустить сопрограмму с помощью StartCoroutine:

StartCoroutine(FlipCardFaceUp(card));

Как сказал Марк Гравелл, блок итератора должен быть пронумерован, чтобы что-то делать, и это то, что делает StartCoroutine (асинхронно и, возможно, другие вещи, необходимые для единства). Часть «асинхронно» также является причиной того, что "Returned from FlipCard" печатается немедленно до завершения сопрограммы.

Если вы хотите дождаться завершения вашей сопрограммы, прежде чем печатать "Return from FlipCard", вы также можете использовать yield:

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

Обратите внимание, что вы не можете использовать yield из Update или FixedUpdate.

РЕДАКТИРОВАТЬ: видя, что вы пытаетесь сделать это в методе OnGUI, лучшим способом может быть просто использование переменной типа Card, чтобы вы могли помнить, какую карту переворачивать. Затем в Update вы можете проверить эту переменную, и если она говорит, что карту нужно перевернуть, вы можете запустить сопрограмму.

24.10.2012
  • Интересный; так что это другой способ, которым единство ожидает, что это будет использовано как сопрограмма 24.10.2012
  • Ничего не изменится, если я вызову метод с StartCoroutine("FlipCardFaceUp", card) 24.10.2012
  • @Lennart Вы пытались использовать yield return StartCoroutine(FlipCardFaceUp(card)), чтобы дождаться завершения сопрограммы? (см. редактирование) 24.10.2012
  • Если я попробую это, то мои карты больше не будут создаваться. Возможно, важно знать, что метод вызывается методом OnGUI(). Должен ли я опубликовать весь свой код? 24.10.2012
  • @Lennart OnGUI может вызываться несколько раз за кадр и не должен задерживаться. Насколько я знаю, вы не можете запустить Coroutines оттуда. Почему бы тебе не заняться этим на другом мероприятии? 24.10.2012
  • Игра памяти полностью построена с элементами единства графического интерфейса (чтобы привыкнуть к ним), поэтому я использую метод OnGUI. Вы правы, что медлить с этим методом нехорошо. Но я не могу понять, почему мой код не работает, если я вызываю FlipCardFaceUp (единственное место, где происходит задержка) с сопрограммой. 24.10.2012
  • @Lennart Я не совсем знаком с ограничениями здесь. Но из того, что я обнаружил, использование сопрограмм в OnGUI не рекомендуется, а также блокирует дальнейшее рисование, пока выполняется метод, и, возможно, поэтому вы не видите никаких результатов. Я рекомендую вам переместить это во что-то подходящее, например «Обновить». 24.10.2012

  • 2

    Добавив yield return, вы сделали его блоком итератора. Блоки итераторов выполняются только когда они повторяются — они демонстрируют "отложенное выполнение". Поэтому, чтобы это работало, вам нужно использовать возвращенное перечисление. В простейшем случае это может быть:

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

    Однако может быть и другой способ, которым единство ожидает, что это будет использовано в качестве сопрограммы update: действительно; см. ответ Botz3000. В большинстве UI блокировка в коде обновления — это плохо (предотвращает отрисовку), но без знания Unity я не могу посоветовать правильную реализацию. Насколько я знаю, вам может понадобиться превратить вызывающий код в блок итератора:

    // 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;
    }
    
    24.10.2012

    3

    Вы можете использовать yield return new WaitForSeconds(2) только в том случае, если вы вызываете свой метод через StartCoroutine. Ваш первый блок кода вернется немедленно, но затем Unity3d позаботится о выполнении остальной части вашего метода (включая 2-секундное ожидание и последующее продолжение).

    24.10.2012
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..