Coroutine acts different when called normally VS. through event handler

The following coroutine, when run on the press of a UI button, will run normally and show "3...2...1...0" and then disappear. However, when run as a part of the event handler delegate HandleRewardBasedVideoClosed (part of AdMob) it will show "3...1..." and then disappear. For the life of me I cannot figure out why it would act differently when called in these two different manners.

public IEnumerator Countdown() {

    timeLeft = 3;

    while (timeLeft >= 0) {
        countdownText.text = timeLeft.ToString();
        yield return new WaitForSecondsRealtime(1.0f);
        timeLeft--;
    }

    if (timeLeft < 0) {
        countdownText.gameObject.SetActive (false);
    }

}

public void HandleRewardBasedVideoClosed(object sender, EventArgs args){

    MonoBehaviour.print("HandleRewardBasedVideoClosed event received");

    if (reward) {
        StartCoroutine ( gm.Countdown ());
    } else
        SceneManager.LoadScene (SceneManager.GetActiveScene ().name);

}

1 answer

  • answered 2018-07-12 07:10 Milan Egon Votrubec

    I have a suspicion about this one. Is it that the count down is in fact doing "3.2 .. 2.1 .. 0.SetActive(false)" so quickly that you're not seeing it running the coroutine twice? If so the following code will resolve that particular problem (if that's the case):

    private bool isCountingDown = false;
    
    public IEnumerator Countdown()
    {
        if ( isCountingDown ) return;
        isCountingDown = true;
    
        for ( int timeLeft = 3; timeLeft >= 0; timeLeft-- )
        {
            countdownText.text = timeLeft.ToString();
            yield return new WaitForSecondsRealtime(1.0f);
        }
    
        countdownText.gameObject.SetActive (false);
        isCountingDown = false;
    }
    
    public void HandleRewardBasedVideoClosed(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleRewardBasedVideoClosed event received");
        if (reward) {
            // This might be a redundant check, as we're doing this in the 
            // Coroutine, but we may as well not go through the process of 
            // calling it in the first place.
            if (! isCountingDown ) StartCoroutine ( gm.Countdown ());
        } else
            SceneManager.LoadScene (SceneManager.GetActiveScene ().name);
    }