Probal Kumar Das
Probal Kumar Das

Reputation: 61

Coroutine WaitForSeconds affected by timeScale

I am working on a simple animation for my UI elements.

I have an animator component which has 2 different animations - ZoomIn and ZoomOut.

These animations are displayed whenever an UI element (e.g. Button) needs to be displayed on the screen.

I normally prefer deactivating the gameobject when not displaying.

I have written the following method for the animations:

private IEnumerator ToggleObjectWithAnimation (GameObject gameObj) {
    Animator gameObjectAnimator = gameObj.GetComponent<Animator> ();   // Animator is set to unscaled time
    if (gameObj.activeSelf == false) {
        gameObj.transform.localScale = new Vector3 (0, 0, 1.0f);
        gameObj.SetActive (true);
        gameObjectAnimator.SetTrigger ("ZoomIn");
        yield return new WaitForSeconds (0.5f);
    } else if(gameObj.activeSelf == true) {
        gameObjectAnimator.SetTrigger ("ZoomOut");
        yield return new WaitForSeconds (0.5f);
        gameObj.SetActive (false);   // code not execute when timescale = 0
    }
    yield return null;
}

The code works fine when for most of the screens, but shows problem when I pause the game using Time.timeScale = 0.

When timescale is 0, the line gameObj.SetActive(false) does not work.

Upvotes: 6

Views: 4475

Answers (1)

derHugo
derHugo

Reputation: 90813

I know it's probably a bit late but:

The problem is not the SetActive but that WaitForSeconds is affected by the Time.timeScale!

The actual time suspended is equal to the given time multiplied by Time.timeScale. See WaitForSecondsRealtime if you wish to wait using unscaled time.

So if you have Time.timescale=0 the WaitForSeconds will never finish!


You should rather use WaitForSecondsRealtime

private IEnumerator ToggleObjectWithAnimation (GameObject gameObj) 
{
    Animator gameObjectAnimator = gameObj.GetComponent<Animator> ();   // Animator is set to unscaled time

    if (gameObj.activeSelf == false) 
    {
        gameObj.transform.localScale = new Vector3 (0, 0, 1.0f);
        gameObj.SetActive (true);
        gameObjectAnimator.SetTrigger ("ZoomIn");
        yield return new WaitForSecondsRealtime (0.5f);
    } 
    else if (gameObj.activeSelf == true) 
    {
        gameObjectAnimator.SetTrigger ("ZoomOut");
        yield return new WaitForSecondsRealtime (0.5f);
        gameObj.SetActive (false);   // code not execute when timescale = 0
    }
    yield return null;
}

Upvotes: 13

Related Questions