Everything after the yield return new wait for seconds is not runnung

Hello,

I am trying to add a delay to the respawn of my player. But when I add the yield return new line nothing runs after it. I have tried addiing debug.log after everyline and they stop out putting once they get to the yield return new line. This respawn is on the player on its own script and there is no other script that would effect the player respawn. The game is also 2D. Here is the code

public GameObject spawnPoint;
public float respawnDelay = 2;

public IEnumerator RespawnPlayer()
{
    gameObject.SetActive(false);
    gameObject.transform.position = spawnPoint.transform.position;
    yield return new WaitForSeconds(respawnDelay);
    gameObject.SetActive(true);
    
}

void OnCollisionEnter2D(Collision2D other)
{
    if (other.gameObject.tag == "Enemy")
    {
        StartCoroutine(RespawnPlayer());
    }
}

Thanks!

Coroutines can’t run on deactivated gameobjects. When you do this:

gameObject.SetActive(false);

the coroutine will be terminated. You could run the coroutine on a singleton manager. A quite and dirty solution is this:

Create a new script called CoroutineManager

public class CoroutineManager : MonoBehaviour
{
    static CoroutineManager m_Instance = null;
    public static CoroutineManager Instance
    {
        get {
            if (m_Instance == null)
            {
                m_Instance = FindObjectOfType<CoroutineManager>();
                if (m_Instance == null)
                    m_Instance = new GameObject("CoroutineManager").AddComponent<CoroutineManager>();
            }
            return m_Instance;
        }
    }
}

Now you can simply do this in your original class:

void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.tag == “Enemy”)
{
CoroutineManager.Instance.StartCoroutine(RespawnPlayer());
}
}

This will run the coroutine on the CoroutineManager gameobject.

This is due to how the yield return new WaitForSeconds function works. Without going too much into detail the issue is that the object is set as not active, so when then yield return new WaitForSeconds is finished waiting it wants to return to a function that is not active. So it simply doesn’t run.


There are two main ways to go about solving this:

  1. Have the responsibility of activation/deactivation of the current game object entrusted to a different object which will never be set as not active.

  2. Don’t deactivate the game object, only its components. with the following code:

    public GameObject spawnPoint;
    public float respawnDelay = 2;
    public IEnumerator RespawnPlayer()
    {
    // hide it
    gameObject.GetComponent ().enabled = false;
    // Stop it from interacting
    gameObject.GetComponent ().enabled = false;

         gameObject.transform.position = spawnPoint.transform.position;
         yield return new WaitForSeconds(respawnDelay);
         // show it
         gameObject.GetComponent<Renderer> ().enabled = true;
         // Start Interacting again
         gameObject.GetComponent<Collider> ().enabled = true;
         
     }
     void OnCollisionEnter2D(Collision2D other)
     {
         if (other.gameObject.tag == "Enemy")
         {
             StartCoroutine(RespawnPlayer());
         }
     }
    

Courutines dont work in the update function.,Also couroutines they dont work in the update function.