Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

yield WaitForSeconds Not Working?

Discussion in 'Scripting' started by punleto, Jun 8, 2011.

  1. punleto

    punleto

    Joined:
    May 13, 2011
    Posts:
    24
    Hi, sorry again for my noobish question but im not sure why it is not working. Basically im on walkerboystudio lab 1:

    http://www.walkerboystudio.com/html/unity_course_lab_1.html

    i've finished the video but im confused what to do to finish the lab...


    First of all, this is the original code for scriptEnemy.js:

    Code (csharp):
    1. var numberOfClicks : int = 2;
    2. var respawnWaitTime : float = 2.0;
    3. var shapeColor : Color[];
    4. var explosion : Transform;
    5. var enemyPoint : int = 1;
    6.  
    7. private var storeClicks : int = 0;
    8.  
    9. function Start ()
    10. {
    11. storeClicks = numberOfClicks;
    12. var startPosition = Vector3 (Random.Range(-6,6), Random.Range(-4,4), 0);
    13. transform.position = startPosition;
    14. RandomColor ();
    15. }
    16. function Update () {
    17.     if (numberOfClicks <= 0)
    18.     {
    19.         if (explosion)
    20.         {
    21.             Instantiate (explosion, transform.position, transform.rotation);
    22.         }
    23.         if (audio.clip)
    24.         {
    25.             audio.Play();
    26.         }
    27.             var position = Vector3 (Random.Range(-3,3),Random.Range(-3,3), 0);
    28.         WaitTime();
    29.         transform.position = position;
    30.         numberOfClicks = storeClicks;  
    31.     }
    32. }
    33.  
    34.     function WaitTime ()
    35.     {
    36.         renderer.enabled = false;
    37.         RandomColor();
    38.         yield WaitForSeconds (respawnWaitTime);
    39.         renderer.enabled = true;
    40.     }
    41.    
    42.    
    43.     function RandomColor ()
    44.     {
    45.         var newColor = Random.Range(0, shapeColor.length);
    46.         renderer.material.color = shapeColor[newColor];
    47.     }
    this script aboveis applied to the "sphere"..there's also one object called playerObject which applied with scriptPlayer.js, and here is what's inside scriptPlayer:

    Code (csharp):
    1.  
    2. var tagName : String;
    3. var rayDistance : float = 0;
    4. var score : int = 0;
    5. var gameTime : float = 5.0;
    6. var loadWaitTime : float = 3.0;
    7. var waitbefore : float = 4.0;
    8. var numberOfPointsToWin : int = 5;
    9.  
    10. function Start ()
    11. {
    12.     InvokeRepeating ("CountDown", 1.0, 1.0); // start the timer countdown
    13. }
    14.  
    15. function Update ()
    16. {
    17. if (Input.GetMouseButtonDown(0))
    18. {
    19.     anjing2();
    20. print ("It works!");
    21. var hit : RaycastHit;
    22. var ray : Ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    23. if (Physics.Raycast (ray, hit, rayDistance))
    24. {
    25.     if (hit.transform.tag == tagName)
    26.     {
    27. var enemyScript = hit.transform.GetComponent(scriptEnemy);
    28. enemyScript.numberOfClicks -= 1;
    29. if (enemyScript.numberOfClicks == 0)
    30. {
    31. score += enemyScript.enemyPoint;
    32. }
    33.     }
    34.     else
    35. {
    36. print ("This is not an enemy!");
    37. }
    38. }
    39. }
    40. }
    41.  
    42. function CountDown ()
    43. {
    44.     if (--gameTime == 0) // gametimer will keep reducing until 0
    45.     {
    46.     CancelInvoke("CountDown");  // to cancel the invoke when it reaches 0
    47.     if ( score >= numberOfPointsToWin )
    48.     {
    49.     Application.LoadLevel ("sceneScreenWin");
    50.     }
    51.     else
    52.     {
    53.         Application.LoadLevel ("sceeneScreenLose");
    54.         }
    55.     }
    56. }
    57.  
    58. function OnGUI ()
    59. {
    60. GUI.Label (Rect(10,10,100,20), "Score: " + score); 
    61. GUI.Label (Rect(10,20,100,20), "Time: " + gameTime);   
    62. }
    63.  
    64.     function anjing2 ()
    65.     {
    66.         yield WaitForSeconds (waitbefore);
    67.     }
    Now they told me to do this by myself:
    How can i do that? i have tried to add another function, similar to "WaitTime ()", i called it "WaitTime2 ()", and use differet variable name for it. I added WaitTime2(); above if explosion() in scriptEnemy.js, but it doesn't work?
     
  2. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    The top one, you are not properly calling the coroutine, you cannot just call it like a normal routine, you MUST create a seperate process for it. To do that, you use StartCoroutine...

    Code (csharp):
    1.  
    2. function Update () {
    3.     if (numberOfClicks <= 0)
    4.     {
    5.         if (explosion)
    6.         {
    7.             Instantiate (explosion, transform.position, transform.rotation);
    8.         }
    9.         if (audio.clip)
    10.         {
    11.             audio.Play();
    12.         }
    13.             var position = Vector3 (Random.Range(-3,3),Random.Range(-3,3), 0);
    14.         [COLOR="red"]StartCoroutine(WaitTime());[/COLOR]
    15.         transform.position = position;
    16.         numberOfClicks = storeClicks;  
    17.     }
    18. }
    19.  
    The bottom part... This:

    InvokeRepeating ("CountDown", 1.0, 1.0);

    is not the way to do a countdown timer.

    You would start a coroutine, display 3, yield for one second, then 2, then yield for one second, then 1, then yield for one second, the let the coroutine end. At the start, you simply set Time.timeScale to zero, at the end make it 1.
     
  3. sidev

    sidev

    Joined:
    Jun 6, 2011
    Posts:
    22
    Hi,

    I think setting the TimeScale to zero won t let the coroutine yield for one second (or three seconds) right?


    sidev
     
  4. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    It does, because I built a countdown timer in a game that did just that.
     
  5. punleto

    punleto

    Joined:
    May 13, 2011
    Posts:
    24
    ok but this wasn't my question. Even if i replace StartCoroutine(WaitTime()); with simply WaitTime();

    it won't make any difference. Atm, with this script:

    if i click the object -> it disappears -> WaitTime -> it reappears

    What i want is not like that but like this...

    if i click the object -> it waits for x seconds -> it disappear -> WaitTime -> it reappears

    now if i want this "it waits for x seconds" to be done, what to add and how?
     
  6. sidev

    sidev

    Joined:
    Jun 6, 2011
    Posts:
    22
    You could move the code into the Update to a CoUpdate. That is instead of void Update(){} you would put a IEnumerator CoUpdate(){}, with a while true loop inside. Then, your could do a yield return StartCoroutine instead of just a StartCoroutine. If you put yield return new WaitForSeconds(3.0) into this coroutine, then it will wait for 3 seconds before letting the code continue.
    Does that make sense ?

    Sidev



    ------------------------------------------------------------
    See "Coroutine Manager" on the Asset Store for easy and powerful coroutines !
     
  7. punleto

    punleto

    Joined:
    May 13, 2011
    Posts:
    24
    OK how to do that? You mean i put:

    IEnumerator CoUpdate()
    {
    StartCoroutine(TheWaitForXSecondsFunction());
    }

    before the if (explosion)? or how? Because it doesn't work...

    *PS: TheWaitForXSecondsFunction is the function for "it waits for x seconds", check my previous post..
     
  8. sidev

    sidev

    Joined:
    Jun 6, 2011
    Posts:
    22
    Hi pulento,

    I took the liberty to write you the code skeleton you should ALWAYS use for your projects.
    This should help you in solving your problems. Please let me know if something is still confusing.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class Punleto : MonoBehaviour {
    6.  
    7.     // Use this for initialization
    8.     void Start () {
    9.         StartCoroutine(CoUpdate()); //This is REALLY IMPORTANT
    10.     }
    11.    
    12.     // Update is called once per frame
    13.     void Update () {
    14.    
    15.     }
    16.    
    17.     //This is the best way to put non performance sensitive code. ALWAYS create a CoUpdate() !!! believe me.
    18.     //Note: Coroutine Manager will help you stop, pause, resume or even reset this coroutine at will! Go for it.
    19.     IEnumerator CoUpdate(){ //ALWAYS have a CoUpdate, you ll thank me later...
    20.         while (true){ //Not necessary if you are using the "loop" mode in Coroutine Manager
    21.            
    22.             /* do some of your code there */
    23.             //NOTE: this code will loop forever until you stop it based on a given condition.
    24.             print("doing some stuff...");
    25.             yield return StartCoroutine(WaitForXSeconds(3.0f));
    26.             print("now we are done waiting. Let s move on");
    27.            
    28.            
    29.             yield return 0; //Do not erase this without caution!
    30.         }
    31.     }
    32.    
    33.     IEnumerator WaitForXSeconds(float seconds){
    34.         print("starting");
    35.         yield return new WaitForSeconds(seconds);
    36.         print("done!");
    37.     }
    38. }
    39.  
    40.  
    41.  
     
  9. sidev

    sidev

    Joined:
    Jun 6, 2011
    Posts:
    22
    Pulento? Are you confortable with C# instead of Javascript? There are similar in Unity but if you want to get into serious code I suggest you spend some time using it. Really.
     
  10. punleto

    punleto

    Joined:
    May 13, 2011
    Posts:
    24
    hi sidev, thanks so much for helping. I actually dont have any experience with C#. I started learning javascript since about 1 month ago, so basically im a total noob. Thanks once again
     
  11. sidev

    sidev

    Joined:
    Jun 6, 2011
    Posts:
    22
    Punleto,

    No problem, enjoy Coroutines ;)

    ------------------------------------------------------------
    See "Coroutine Manager" on the Asset Store for easy and powerful coroutines !
     
  12. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    Wha... so what you want to do is add the wait for x seconds into the wait time.... and I thought it was complicated.....

    Same script as before, just change your WaitTime coroutine to this:
    Code (csharp):
    1.  
    2.     function WaitTime ()
    3.     {
    4.         yield WaitForSeconds (respawnWaitTime);
    5.         renderer.enabled = false;
    6.         RandomColor();
    7.         yield WaitForSeconds (respawnWaitTime);
    8.         renderer.enabled = true;
    9.     }
    10.  
    If you want to specify the Wait time per click.. then you would need this:
    Code (csharp):
    1.  
    2.     function WaitTime (X : float)
    3.     {
    4.         yield WaitForSeconds (X);
    5.         renderer.enabled = false;
    6.         RandomColor();
    7.         yield WaitForSeconds (respawnWaitTime);
    8.         renderer.enabled = true;
    9.     }
    10.