Unity Coroutine не ждет - PullRequest
       80

Unity Coroutine не ждет

0 голосов
/ 13 июля 2020

Я создаю игру, в которой хочу, чтобы оверлей появлялся в течение определенного количества секунд, прежде чем исчезнуть. Я использую для этого Coroutine, но теперь она работает. Есть ли способ решить эту проблему, или я должен сделать это по-другому. Я не получаю никаких ошибок, но coverObject не отображается в течение 3 секунд и скрывается в течение 2 секунд, как указано в коде.

Код:

void playRound()
{
    coverObject.gameObject.SetActive(true);
    for (int i = 0; i < keys - 1; i++)
    {
        GameObject instantiated = Instantiate(key);
    }
    waitSecs(3);
    coverObject.gameObject.SetActive(true);

    GameObject instantiatedCorrect = Instantiate(key);
    correctKey = instantiatedCorrect;

    waitSecs(2);
    coverObject.gameObject.SetActive(false);
}
    
void waitSecs(int seconds)
{
    StartCoroutine(WaitSecsCoroutine(seconds));
}

IEnumerator WaitSecsCoroutine(int seconds) 
{
    yield return new WaitForSeconds(seconds);
}

Ответы [ 2 ]

2 голосов
/ 13 июля 2020

Ваша сопрограмма ждет ... НО: сопрограмма не задерживает ничего в методе, который запускает ее сам. Она только задерживает код внутри сопрограммы!

Таким образом, так, как вы это делаете, он просто выполнит остальную часть кода в playRound без какого-либо ожидания.

То, что вы хотите сделать, будет запускать все это в Coroutine, например,

void playRound()
{
    StartCoroutine(PlayRoundRoutine());
}

IEnumerator PlayRoundRoutine() 
{
    coverObject.gameObject.SetActive(true);
    for (int i = 0; i < keys - 1; i++)
    {
        GameObject instantiated = Instantiate(key);
    }

    yield return new WaitForSeconds(3f);

    coverObject.gameObject.SetActive(true);

    GameObject instantiatedCorrect = Instantiate(key);
    correctKey = instantiatedCorrect;

    yield return new WaitForSeconds(2f);

    coverObject.gameObject.SetActive(false);
}
1 голос
/ 13 июля 2020

ваш метод playRound будет продолжать работать, пока сопрограмма WaitSecsCoroutine уступает. Это связано с тем, что управление возвращается вызывающему методу, как только достигается оператор yield return.

Происходит следующее:

  • playRound вызывается
  • ваши GameObjects создаются
  • waitSecs вызывается
  • waitSecs вызовы сопрограммы waitSecsCoroutine
  • waitSecsCoroutine достигает yield return new WaitForSeconds()
  • Управление теперь возвращается обратно к waitSecs, которое, в свою очередь, возвращается к PlayRound
  • playRound продолжается с coverObject.gameObject.SetActive(true); и последующим кодом, пока waitSecsCoroutine все еще ждет.

Что вам нужно сделать, так это сделать playRound сопрограмму и использовать yield return WaitSecsCoroutine, чтобы функция остановила свое выполнение до тех пор, пока WaitSecsCoroutine не завершится:

IEnumerator playRound()
{
    coverObject.gameObject.SetActive(true);
    for (int i = 0; i < keys - 1; i++)
    {
        GameObject instantiated = Instantiate(key);
    }
    yield return WaitSecsCoroutine(3);//This now waits until WaitSecsCoroutine is finished
    coverObject.gameObject.SetActive(true);
    GameObject instantiatedCorrect = Instantiate(key);
    correctKey = instantiatedCorrect;
    yield return WaitSecsCoroutine(2);
    coverObject.gameObject.SetActive(false);
}

Однако обратите внимание, что вы также можете просто вызвать WaitForSeconds непосредственно из вашего playRoudn метода, если это сопрограмма, без необходимости отдельной функции

IEnumerator playRound()
{
    coverObject.gameObject.SetActive(true);
    for (int i = 0; i < keys - 1; i++)
    {
        GameObject instantiated = Instantiate(key);
    }
    yield return new WaitForSeconds(3);
    coverObject.gameObject.SetActive(true);
    GameObject instantiatedCorrect = Instantiate(key);
    correctKey = instantiatedCorrect;
    yield return new WaitForSeconds(2);
    coverObject.gameObject.SetActive(false);
}

В качестве альтернативы вы можете переместить код, который хотите выполнить, после ожидания в ваш метод WaitSecsCoroutine.

...