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 is being called just once

Discussion in 'Scripting' started by Shadston, Jul 10, 2015.

  1. Shadston

    Shadston

    Joined:
    Apr 24, 2015
    Posts:
    13
    I am trying to create my first quite advanced game. I'm supposed to use coroutine in one moment, which works similary, but is not this same. Here I just wanted to present some example. Debug.Log should show value after 1 sec pause, which should look like count down. Imo everything here is logically ok, but it doesn't seem to work, I can't find what am I doing wrong. I would appreciate some help.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class NewBehaviourScript : MonoBehaviour {
    5.  
    6.     private bool useCoroutine;
    7.     private float counter;
    8.     // Use this for initialization
    9.     void Start ()
    10.     {
    11.         useCoroutine = true;
    12.         counter = 10;
    13.     }
    14.  
    15.     // Update is called once per frame
    16.     void Update ()
    17.     {
    18.         counter -= Time.deltaTime;
    19.         if (useCoroutine)
    20.         {
    21.             StartCoroutine(Show));
    22.         }
    23.         else
    24.         {
    25.             StopCoroutine(Show ());
    26.         }
    27.     }
    28.  
    29.     IEnumerator Show()
    30.     {
    31.         Debug.Log ("Value: " + counter);
    32.         if (counter < 0)
    33.         {
    34.             useCoroutine = false;
    35.         }
    36.         yield return new WaitForSeconds(1);
    37.     }
    38. }
     
    Last edited: Jul 10, 2015
  2. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    first problem

    you're immediately stopping the coroutine in the next frame by setting the boolean to false

    second problem
    Code (csharp):
    1.  
    2. IEnumerator Show()
    3. {
    4. ..
    5. yield return new WaitForSeconds(1);
    6. ..
    7. }
    8.  
    do something, wait 1 second, do the rest. The end. There is no loop inside that coroutine.
     
  3. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,194
  4. Shadston

    Shadston

    Joined:
    Apr 24, 2015
    Posts:
    13
    Hm... So how do I turn on/off coroutine depending on bool value? Is there any other way to check if bool value has changed than method update?
     
  5. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,739
    you would do that like this.

    Code (CSharp):
    1.     private IEnumerator Show() {
    2.         while (myBool) {
    3.             // do Logic here
    4.             yield return new WaitForSeconds(1f);
    5.         }
    6.     }
    7.  
    once that bool becomes false the loop will break.

    There is no way to simply just enabe and disable a coroutine best you can do is breaking the loop like that and starting it anew.

    If this is a action you need to enable and disable through out your game your best off making it its own component, or method that runs in Unitys Update method instead of a coroutine.


    A simple way of having part of your Update run every second would be like this.
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class Test : MonoBehaviour {
    4.     private float _lastUpdate;
    5.  
    6.     private void Update() {
    7.         if (Time.time - _lastUpdate >= 1f) {
    8.             Debug.Log("Do Stuff here");
    9.             _lastUpdate = Time.time;
    10.         }
    11.     }
    12. }
    13.  
     
    Last edited: Jul 10, 2015
  6. Shadston

    Shadston

    Joined:
    Apr 24, 2015
    Posts:
    13
    Thank you passerbycmc, your advise was great! I was able to make my example code work exactly how I wanted! But the real problem doesn't seem to be as easy in my real case. I've tried to apply this method in my original project, but I met a wall again. In PlayerController script I have bool variable bonus. When bonus becomes true (player catches bonus icon) this script should start spawn bonus pick ups. It does work only when I replace player.GetComponent<PlayerController>().bonus with 'true'. Otherwise it just does not access while loop in method SpawnBonusPickUp. Is this problem result of methods call order?

    Code (CSharp):
    1. void Start()
    2.     {
    3.         StartCoroutine(SpawnBonusPickUp());
    4.         InvokeRepeating ("SpawnPickUp", 0, pickUpSpawnTime);
    5.         InvokeRepeating ("SpawnBonus", 15, bonusSpawnTime);
    6.     }
    7.  
    8.     public void SpawnPickUp ()
    9.     {
    10.         if (!gameOver)
    11.         {
    12.             int spawnPointX = Random.Range (-9, 9);
    13.             int spawnPointZ = Random.Range (-9, 9);
    14.             Vector3 pickUpSpawn = new Vector3(spawnPointX, 0.5f, spawnPointZ);
    15.             if(pickUpSpawn != player.transform.position)
    16.             {
    17.                 var pickUpInstance = Instantiate (pickUp, pickUpSpawn, transform.rotation);
    18.                 Destroy(pickUpInstance, pickUpDestroyTime);
    19.             }
    20.         }
    21.     }
    22.  
    23.     public IEnumerator SpawnBonusPickUp()
    24.     {
    25.         while (player.GetComponent<PlayerController>().bonus)
    26.         {
    27.             yield return new WaitForSeconds(0.25f);
    28.             if (!gameOver)
    29.             {
    30.                 int spawnPointX = Random.Range (-9, 9);
    31.                 int spawnPointZ = Random.Range (-9, 9);
    32.                 Vector3 pickUpSpawn = new Vector3(spawnPointX, 0.5f, spawnPointZ);
    33.                 if(pickUpSpawn != player.transform.position)
    34.                 {
    35.                     var pickUpInstance = Instantiate (pickUp, pickUpSpawn, transform.rotation);
    36.                     Destroy(pickUpInstance, pickUpDestroyTime);
    37.                 }
    38.             }
    39.         }
    40.         StopCoroutine (SpawnBonusPickUp ());
    41.     }
     
  7. Shadston

    Shadston

    Joined:
    Apr 24, 2015
    Posts:
    13
    I found that my coroutine is not looped. It starts once and after that it just 'dies'. I've tried sereval ways to rerun it, but it didn't work. I've spent hours looking for solution and still got nothing >_>