Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Coroutine runs immediately instead of waiting

Discussion in 'Scripting' started by teknophyl, Jul 20, 2014.

  1. teknophyl

    teknophyl

    Joined:
    Jun 22, 2014
    Posts:
    51
    I'm trying to create a Coroutine that pauses for 2 seconds for a respawn.

    My coroutine is running, and I can see its output in the console, but it never waits - it runs immediately even though I am specifying a specific pause time. I've tried something similar with Invoke and THAT doesn't wait either.

    What am I doing wrong?
    Code (CSharp):
    1. IEnumerator RespawnPlayer()
    2.     {
    3.         Debug.Log("hello world");
    4.         yield return new WaitForSeconds(20); //obnoxious pause for debugging, yet above still prints immediately to console
    5.      
    6.  
    7.     }
    8.  
    9.     void OnTriggerEnter(Collider other)
    10.     {
    11.         // avoid collision with the boundary collider
    12.         if (other.tag == "Boundary") return;
    13.  
    14.  
    15.         // boom! for the asteroid
    16.         Instantiate (explosion, transform.position, transform.rotation);
    17.         gameController.AddScore(scoreValue);
    18.  
    19.         // boom! for the player if he crashes into the asteroid
    20.         if (other.collider.tag == "Player")
    21.         {
    22.             gameController.livesLeft -= 1;
    23.  
    24.             Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
    25.  
    26.             if (gameController.livesLeft == 0)
    27.             {
    28.                 Destroy(other.gameObject);
    29.                 gameController.GameOver();
    30.             }
    31.             else
    32.             {
    33.                 StartCoroutine(RespawnPlayer ()); // THIS DOES NOT PAUSE
    34.             }
    35.         }
    36. }
     
  2. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    How about this;

    Code (CSharp):
    1. IEnumerator RespawnPlayer()
    2.     {
    3.         yield return new WaitForSeconds(20);
    4.         Debug.Log("hello world");
    5.     }
     
  3. TRALLALAL

    TRALLALAL

    Joined:
    Sep 7, 2013
    Posts:
    132
    ^This, in your code the first thing it does is write the string to the console.
     
  4. teknophyl

    teknophyl

    Joined:
    Jun 22, 2014
    Posts:
    51
    This didn't work for me either. I did try this earlier, but the debug line is never written.
     
  5. zDemonhunter99

    zDemonhunter99

    Joined:
    Apr 23, 2014
    Posts:
    478
    Code (CSharp):
    1. void IEnumerator RespawnPlayer()
    2. {
    3.   yield return new WaitForSeconds(20);
    4. Debug.Log("Hello World!");
    5. }
    It ought to work perfectly fine...
    There must be something wrong in your code. Post it here, so that we can view it and help you out.
     
  6. teknophyl

    teknophyl

    Joined:
    Jun 22, 2014
    Posts:
    51
    Problem Statement:
    Add a set number of lives for my player ship. When the ship is destroyed, I want to deduct 1 life from a counter, wait 2 seconds, then display the ship.

    I'm using the 2D shooter tutorial as a starting point.

    Note that the GameController contains nothing exotic; I just added another variable, GUIText, and method to update the number of lives remaining. This seems to work correctly in spite of the odd behavior of my Coroutine.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class DestroyByContact : MonoBehaviour {
    5.  
    6.     public GameObject explosion;
    7.     public GameObject playerExplosion;
    8.     public int scoreValue;
    9.     private GameController gameController;
    10.  
    11.     void Start()
    12.     {
    13.         GameObject gameControllerObject = GameObject.FindWithTag ("GameController");
    14.  
    15.         if (gameControllerObject != null) {
    16.             gameController = gameControllerObject.GetComponent<GameController>();
    17.  
    18.                 }
    19.  
    20.         if (gameControllerObject == null) {
    21.             Debug.Log("Cannot find 'GameController' object");
    22.                 }
    23.     }
    24.  
    25.  
    26.     IEnumerator RespawnPlayer()
    27.     {
    28.      
    29.         yield return new WaitForSeconds(4);
    30.         Debug.Log("hello world");
    31.  
    32.     }
    33.  
    34.     void OnTriggerEnter(Collider other)
    35.     {
    36.         // avoid collision with the boundary collider
    37.         if (other.tag == "Boundary") return;
    38.  
    39.  
    40.         // boom! for the asteroid
    41.         Instantiate (explosion, transform.position, transform.rotation);
    42.         gameController.AddScore(scoreValue);
    43.  
    44.         // boom! for the player if he crashes into the asteroid
    45.         if (other.collider.tag == "Player")
    46.         {
    47.             gameController.livesLeft -= 1;
    48.  
    49.             Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
    50.  
    51.             if (gameController.livesLeft == 0)
    52.             {
    53.                 Destroy(other.gameObject);
    54.                 gameController.GameOver();
    55.             }
    56.             else
    57.             {
    58.                 StartCoroutine(RespawnPlayer ());
    59.             }
    60.         }
    61.  
    62.  
    63.         if (other.gameObject.tag != "Player")
    64.         {
    65.         // first destroy the laser bolt
    66.         Destroy(other.gameObject);
    67.  
    68.  
    69.         // next the asteroid itself and all children/attached components
    70.         Destroy(gameObject);
    71.         }
    72.     }
    73. }
    74.  
     
  7. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,398
    You're destroying the game object, which also means any scripts attached to it, so there's no code running and therefore no waiting.

    --Eric
     
  8. teknophyl

    teknophyl

    Joined:
    Jun 22, 2014
    Posts:
    51
    I've been trying to wrap my head around this. That's why I put the conditional around the Destroy calls in OnTriggerEnter; I guess I haven't done that right.
     
  9. rrh

    rrh

    Joined:
    Jul 12, 2012
    Posts:
    331
    So what makes the ship not display?
     
  10. teknophyl

    teknophyl

    Joined:
    Jun 22, 2014
    Posts:
    51
    Thanks for the hints everyone. I *think* I have it now. Is there any non-obvious issue with the following? I paid close attention to the Hierarchy and noticed no rogue objects being created during and after the Game Over condition.

    Code (CSharp):
    1. IEnumerator RespawnPlayer(GameObject gameObject)
    2.     {
    3.  
    4.         gameObject.SetActive(false);
    5.         yield return new WaitForSeconds(2.0f);
    6.         gameObject.SetActive(true);
    7.     }
    8.  
    9.     void OnTriggerEnter(Collider other)
    10.     {
    11.         // avoid collision with the boundary collider
    12.         if (other.tag == "Boundary") return;
    13.  
    14.  
    15.         // boom! for the asteroid
    16.         Instantiate (explosion, transform.position, transform.rotation);
    17.         gameController.AddScore(scoreValue);
    18.  
    19.         //// boom! for the player if he crashes into the asteroid
    20.    
    21.         if (other.collider.tag != "Player")
    22.         {
    23.             // first destroy the laser bolt
    24.             Destroy(other.gameObject);
    25.  
    26.  
    27.             // next the asteroid itself and all children/attached components
    28.             Destroy(gameObject);
    29.         }
    30.         else
    31.         {
    32.             if (other.collider.tag == "Player")
    33.             {
    34.                 gameController.livesLeft -= 1;
    35.  
    36.                 Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
    37.  
    38.                 if (gameController.livesLeft == 0)
    39.                 {
    40.                     Destroy(other.gameObject);
    41.                     Destroy(gameObject);
    42.                     gameController.GameOver();
    43.                 }
    44.                 else
    45.                 {
    46.  
    47.                     StartCoroutine(RespawnPlayer(other.gameObject));
    48.                 }
    49.             }
    50.         }
    51.        
    52.     }