Home > database >  Why is the code after yield return not executed
Why is the code after yield return not executed

Time:10-28

The GameObject in my Unity project should deactivate and then reactivate after a set time. It does deactivate but never reactivates. The object does not deactivate itself so it cant be because of that.

neither

public class PickupController : MonoBehaviour
{ 
    public IEnumerator Reactivate(float seconds, GameObject target)
    {
        target.SetActive(false);
        while (!target.gameObject.active)
        {
            yield return new WaitForSeconds(seconds);
        }
        target.SetActive(true);
    }
}

or

public class PickupController : MonoBehaviour
{ 
    public IEnumerator Reactivate(float seconds, GameObject target)
    {
        target.SetActive(false);
        yield return new WaitForSeconds(seconds);
        target.SetActive(true);
    }
}

works.

Thanks for the help. :)

CodePudding user response:

Coroutines are stopped when you deactivate the GameObject the coroutine is attached to. Or, I could just quote the Unity docs here:

To stop a coroutine, use StopCoroutine and StopAllCoroutines. A coroutine also stops if you’ve set SetActive to false to disable the GameObject the coroutine is attached to. Calling Destroy(example) (where example is a MonoBehaviour instance) immediately triggers OnDisable and Unity processes the coroutine, effectively stopping it. Finally, OnDestroy is invoked at the end of the frame.

If this is the functionality you’re looking for, use a coroutine attached to a different GameObject. It looks like your code was trying to do just that, with the target argument.

CodePudding user response:

To add to this answer from how you implemented and describe this to me it seems like you are calling this the following way

public class ScriptOnYourTargetObject : MonoBehaviour
{
    
        ...
        StartCoroutine(thePickupController.Reactivate(6, gameObject);
        ...
}

=> This would mean the routine still STOPS the moment this object is deactivated!

In which script the IEnumerator is implemented doesn't mater but on which MonoBehaviour instance you are executing StartCoroutine since this instance will be running the routine!

If this is the case you could change that and rather go e.g.

public class PickupController : MonoBehaviour
{ 
    public void Reactivate(float seconds, GameObject target)
    {
        StartCoroutine(ReactivateRoutine(seconds, target));
    }

    private IEnumerator ReactivateRoutine(float seconds, GameOvbject target)
    {
        target.SetActive(false);
        while (!target.gameObject.active)
        {
            yield return new WaitForSeconds(seconds);
        }
        target.SetActive(true);
    }
}

If actually everything is like you say, the object running the routine is not deactivated then I guess the last thing to check would only be:

Do you maybe play around with the Time.timeScale?

If this is set to something smaller then 1 then WaiForSeconds will take accordingly longer. If it is set to 0 then WaitForSeconds will never finish

=> use WaitForSecondsRealtime instead

  • Related