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

Waiting for seconds in Update()

Discussion in 'Scripting' started by robbmcmahan, Mar 18, 2009.

Thread Status:
Not open for further replies.
  1. robbmcmahan

    robbmcmahan

    Joined:
    Feb 25, 2009
    Posts:
    99
    Since you can't use "yield new WaitForSeconds()" in the Update() function what is the best way to make something pause for 1 second instead of firing off every frame?


    Thanks
     
    Ascyt likes this.
  2. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    1. don't use update. it will be called on each frame
    2. Use Startcoroutine and start it in "Start". Make it yield for a second or whatever timeframe you want
     
  3. robbmcmahan

    robbmcmahan

    Joined:
    Feb 25, 2009
    Posts:
    99
    Right. I understand that but the problem is that I need to run it when a touch happens on the iPhone so it needs to run from update().
     
    Ascyt likes this.
  4. AngryAnt

    AngryAnt

    Keyboard Operator Moderator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    Something like this?
    Code (csharp):
    1. private bool beingHandled = false;
    2.  
    3. public void Update()
    4. {
    5.     if( /*some case  */ !beingHandled )
    6.     {
    7.         StartCoroutine( HandleIt() );
    8.     }
    9. }
    10.  
    11. private IEnumerator HandleIt()
    12. {
    13.     beingHandled = true;
    14.     // process pre-yield
    15.     yield return new WaitForSeconds( 1.0f );
    16.     // process post-yield
    17.     beingHandled = false;
    18. }
     
  5. robbmcmahan

    robbmcmahan

    Joined:
    Feb 25, 2009
    Posts:
    99
    Ive tried this. Here is my code... Can anyone see why it's not waiting and just keeps counting down as fast as the frames?

    Code (csharp):
    1.  
    2.  
    3. function ReduceFuel(){
    4.  
    5.     while(FuelLevel > 1)
    6.     {
    7.        
    8.         FuelLevel -= 1;
    9.         yield new WaitForSeconds(1);
    10.        
    11.     }  
    12.  
    13. }
    14.  
    15. function Update () {
    16.        
    17.    
    18.     for (var evt : iPhoneTouch in iPhoneInput.touches)
    19.     {
    20.        
    21.         var element : GUIElement = guiLayer.HitTest (Input.mousePosition);
    22.        
    23.        
    24.             if (evt.phase == iPhoneTouchPhase.Stationary)
    25.             {
    26.  
    27.                         if(element == ArrowUp || element == ArrowDown)
    28.                         {  
    29.                            
    30.                                 ReduceFuel();
    31.                                
    32.                         }
    33.                
    34.             }
    35. }
    36.  
    37.  
     
  6. CoherentInk

    CoherentInk

    Joined:
    Jul 16, 2006
    Posts:
    216
    The reason that isn't working as you'd expect is that ReduceFuel isn't running as a coroutine. As AngryAnt suggested, you should start it as a coroutine:
    Code (csharp):
    1. StartCoroutine(ReduceFuel());
     
  7. robbmcmahan

    robbmcmahan

    Joined:
    Feb 25, 2009
    Posts:
    99
    I was thinking a coroutine was just a function. Whats the difference between a coroutine and a function?
     
  8. rom

    rom

    Joined:
    Jul 2, 2006
    Posts:
    265
  9. AngryAnt

    AngryAnt

    Keyboard Operator Moderator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    A coroutine is a function which will be continuously executed over several frames - depending on how you yield it. All coroutines are executed after the last update call and when you yield, the function ends - only to be re-run from the point of the yield statement once the yield statement has been "completed".
     
    LueSoSo likes this.
  10. robbmcmahan

    robbmcmahan

    Joined:
    Feb 25, 2009
    Posts:
    99
    I'm using Javascript and not C#. I think I remember reading in the docs that you had to call co-routines for C# but that Javascript automatically would do this when you call a function.
     
  11. CoherentInk

    CoherentInk

    Joined:
    Jul 16, 2006
    Posts:
    216
    Have a look at the script reference (my best friend) for information on coroutines and the yield statement. At the bottom of the page it says:

    So you do need to use StartCoroutine when calling from Update.
     
  12. robbmcmahan

    robbmcmahan

    Joined:
    Feb 25, 2009
    Posts:
    99
    Ok, I did this and still get the same result:

    Code (csharp):
    1.  
    2.  
    3.        
    4.             if (evt.phase == iPhoneTouchPhase.Stationary)
    5.             {
    6.  
    7.                         if(element == ArrowUp || element == ArrowDown)
    8.                         {  
    9.                            
    10.                                 StartCoroutine(ReduceFuel());
    11.                                
    12.                         }
    13.                
    14.             }
    15.  
    16.  
    [/quote]
     
  13. robbmcmahan

    robbmcmahan

    Joined:
    Feb 25, 2009
    Posts:
    99
    I guess I should have put all the code.....this is what I have now and it still does not waitforseconds....wierd....


    Code (csharp):
    1.  
    2.  
    3.  
    4.  
    5. function ReduceFuel(){
    6.  
    7.     while(FuelLevel > 1)
    8.     {
    9.        
    10.         FuelLevel -= 1;
    11.         yield new WaitForSeconds(5);
    12.        
    13.     }  
    14.  
    15. }
    16.  
    17. function Update () {
    18.    
    19.        
    20.     //PlayWarnings();      
    21.    
    22.     for (var evt : iPhoneTouch in iPhoneInput.touches)
    23.     {
    24.        
    25.         var element : GUIElement = guiLayer.HitTest (Input.mousePosition);
    26.        
    27.        
    28.             if (evt.phase == iPhoneTouchPhase.Stationary)
    29.             {
    30.  
    31.                         if(element == ArrowUp || element == ArrowDown)
    32.                         {  
    33.                            
    34.                                 StartCoroutine(ReduceFuel());
    35.                                
    36.                         }
    37.                
    38.             }
    39.  
    40. }
    41.  
    42.  
    43.  
    44.  
     
  14. CoherentInk

    CoherentInk

    Joined:
    Jul 16, 2006
    Posts:
    216
    Since you're using JScript, you should drop the new keyword in your WaitForSeconds line:
    Code (csharp):
    1. yield WaitForSeconds(5);
    You only need new in C# code (where yield statements get rather complicated).
     
  15. robbmcmahan

    robbmcmahan

    Joined:
    Feb 25, 2009
    Posts:
    99
    I've actually used the keyword new throughout my entire game and it's worked as i've wanted it too. I went ahead and tried it without it as you suggested and it still isn't working ... any other suggestions?
     
  16. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,398
    Not with Javascript, where it does that for you. The only reason to use StartCoroutine in Javascript is if you want to be able to use StopCoroutine on the routine you're starting.

    --Eric
     
  17. robbmcmahan

    robbmcmahan

    Joined:
    Feb 25, 2009
    Posts:
    99
    Thats what I sorta remembered reading..... Eric, do you have any suggestions to pull this off? It seems like anything I call in Update() acts as if it were in Update().


    What I'm trying to accomplish is a steady fuel consumption as long as the button is being pushed.
     
  18. CoherentInk

    CoherentInk

    Joined:
    Jul 16, 2006
    Posts:
    216
    What you probably want to do is multiply the amount by Time.deltaTime so that you get a constant rate regardless of frame rate. You can do this inside the Update function:

    Code (csharp):
    1. fuelLevel -= Time.deltaTime * ratePerSecond;
    As for the issue of coroutines, JScript and Update, there is a discrepancy in the documentation. The description for StartCoroutine does clearly state that:
    Yet the overview does say to use StartCoroutine to start a function from Update to use a yield statement. There is some issue here, hopefully Eric or one of the Unity gods has an answer!
     
  19. robbmcmahan

    robbmcmahan

    Joined:
    Feb 25, 2009
    Posts:
    99
    Good thought.....problem is, I've tried that too and it doesn't work either. I plugged your code and tried again using various ratesPerSecond and no matter what it is the numbers still count down per frame.

    :(
     
  20. CoherentInk

    CoherentInk

    Joined:
    Jul 16, 2006
    Posts:
    216
    Is there any other part of your code that accesses fuelLevel? If you set the ratePerSecond to 0.2, that would be the same as 1 unit per 5 seconds, but you'll see it drop continuously while the button is pressed. You're saying that you press the button and it is dropping at a rate of 1 unit per frame?
     
  21. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,398
    That's correct, but remember that you don't need to explicitly write StartCoroutine in Javascript, so there isn't any contradiction there. :) You're still using StartCoroutine; it's just implicit.

    You probably need to do what AngryAnt said and use a "beingHandled" boolean or something similar to check if the coroutine is already running, and block any further calls if so. Because the way it is now, you'd be starting the coroutine once per frame in every Update call, so in short order you'd have it running many times per second.

    --Eric
     
  22. robbmcmahan

    robbmcmahan

    Joined:
    Feb 25, 2009
    Posts:
    99

    Yep, Tried that too. But....tried it again.....here's the code...maybe somethings not right in my logic..

    Code (csharp):
    1.  
    2.  
    3. var FuelIsRunning : boolean = false;
    4.  
    5. function ReduceFuel(){
    6.  
    7.    
    8.     while(FuelLevel > 1  FuelIsRunning == true)
    9.     {
    10.        
    11.         FuelLevel -= 1;
    12.         yield WaitForSeconds(1);
    13.     }  
    14.  
    15. }
    16.  
    17. function Update () {
    18.            
    19.    
    20.     for (var evt : iPhoneTouch in iPhoneInput.touches)
    21.     {
    22.        
    23.         var element : GUIElement = guiLayer.HitTest (Input.mousePosition);
    24.        
    25.        
    26.             if (evt.phase == iPhoneTouchPhase.Stationary)
    27.             {
    28.  
    29.                         if(element == ArrowUp || element == ArrowDown  FuelIsRunning == false)
    30.                         {  
    31.                                 FuelIsRunning = true;
    32.                                 ReduceFuel();
    33.                                
    34.                                
    35.                         }
    36.                
    37.             }
    38.  
    39.         if (evt.phase == iPhoneTouchPhase.Ended)
    40.             {
    41.                
    42.                 if(element == ArrowUp)
    43.                     {
    44.                        
    45.                         FuelIsRunning = false;
    46.                    
    47.                     }
    48.        
    49.                 if(element == ArrowDown)
    50.                     {
    51.                         FuelIsRunning = false;
    52.                                
    53.                     }
    54.    
    55.             }
    56.            
    57.                            
    58.        
    59.     }
    60.  
    61.  
    62.  
    63.  
    64.  
     
  23. CoherentInk

    CoherentInk

    Joined:
    Jul 16, 2006
    Posts:
    216
    All you should need is this:
    Code (csharp):
    1.  
    2. function Update () {
    3.     for (var evt : iPhoneTouch in iPhoneInput.touches)
    4.     {
    5.         var element : GUIElement = guiLayer.HitTest (Input.mousePosition);
    6.         if (evt.phase == iPhoneTouchPhase.Stationary)
    7.         {
    8.             if (element == ArrowUp || element == ArrowDown)
    9.             {  
    10.                 FuelLevel -= Time.deltaTime * 0.2;
    11.             }
    12.         }
    13.     }
    14. }
    15.  
    But you tried that and it didn't work?
     
  24. robbmcmahan

    robbmcmahan

    Joined:
    Feb 25, 2009
    Posts:
    99


    Yes, I tried this again and it doesn't work. Does anyone else have any suggestions?
     
  25. Nevesola

    Nevesola

    Joined:
    Jan 14, 2009
    Posts:
    14
    Your code snippet doesn't show where you declared/defined FuelLevel and its starting value. Could you post that as well? Or check to make sure its a float value, not an integer.
     
  26. robbmcmahan

    robbmcmahan

    Joined:
    Feb 25, 2009
    Posts:
    99

    Well, Actually it was a int and I didn't catch that....but....I changed it and it's still not working.
     
  27. robbmcmahan

    robbmcmahan

    Joined:
    Feb 25, 2009
    Posts:
    99
    Stop the presses....I changed the wrong var. That was the problem the entire time...... :eek: ok, now I feel like an idiot.
     
  28. DrHotbunz

    DrHotbunz

    Joined:
    Feb 14, 2009
    Posts:
    315
    Still funny 6 months later :)
     
  29. doma87

    doma87

    Joined:
    Jul 14, 2014
    Posts:
    1
    Still funny 5 years later :D
     
  30. Borjka

    Borjka

    Joined:
    Apr 24, 2016
    Posts:
    3
    Dont understand but still funny and usefull 7 years later
     
  31. amirm57

    amirm57

    Joined:
    Dec 17, 2014
    Posts:
    2
    I read somewhere that calling coroutine function in Update makes a huge performance issue.
     
  32. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    Starting a coroutine from Update should not cause performance issues.
    A problem would be to start the same coroutine each time Update is invoked, that is on each frame. But that would be considered a bug.

    Do you still have a reference to what you've read?
    What do you want to do with coroutines?
     
    Last edited: Mar 13, 2017
  33. amirm57

    amirm57

    Joined:
    Dec 17, 2014
    Posts:
    2
    Unfortunately i don't remember the reference .
     
  34. maaz0011

    maaz0011

    Joined:
    Jan 4, 2017
    Posts:
    3
  35. Deniz2014

    Deniz2014

    Joined:
    Apr 27, 2014
    Posts:
    8
    I wanted to wait x Seconds in the Update() before continuing. So you cannot use the yield there (don't want to start a coroutine every frame right?)

    So if someone, like me, searched this / needs this in and for the Update():

    Code (CSharp):
    1. private float timer = 0;
    2.  
    3. private float timerMax = 0;
    4.  
    5. void Update ()
    6. {
    7.    text += "Allow yourself to see what you don’t allow yourself to see.";
    8.  
    9.    if(!Waited(3)) return;
    10.  
    11.    text += "\n\nPress any key!";
    12. }
    13.  
    14.  
    15. private bool Waited(float seconds)
    16. {
    17.     timerMax = seconds;
    18.  
    19.     timer += Time.deltaTime;
    20.  
    21.     if (timer >= timerMax)
    22.     {
    23.         return true; //max reached - waited x - seconds
    24.     }
    25.  
    26.     return false;
    27. }
     
  36. Archviz3d

    Archviz3d

    Joined:
    Apr 4, 2016
    Posts:
    92
    Thanks!!! :)
     
  37. dhruvmohandatta1234

    dhruvmohandatta1234

    Joined:
    Jan 13, 2018
    Posts:
    2
    why cant unity create a simple wait function in monodevelop
     
  38. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    There are coroutines for that, or simply a timer/counter in Update(). Or even Invoke, in some circumstances. :)
     
  39. Indie_Dev

    Indie_Dev

    Joined:
    Dec 29, 2017
    Posts:
    35
    I could be wrong, but if you're waiting for something to be touched, couldn't you use drag or pointer events, to eliminate update out of the equation..?

    Then use that to invoke or start coroutine?

    It's not much, I know, but it would eliminate an unnecessary "if button pressed" check 50-100 times per second when it's not needed, wouldn't it?

    I think you can control how long/often an event like that fires too, can't you?
     
  40. m-y

    m-y

    Joined:
    Sep 22, 2013
    Posts:
    470
    Bravo
     
  41. shreyanshanchlia

    shreyanshanchlia

    Joined:
    Jun 7, 2018
    Posts:
    21
    still funny 10 years later.
    don't worry happens with everyone:):D
     
  42. QQQ_QQQ

    QQQ_QQQ

    Joined:
    Jul 12, 2019
    Posts:
    15

    I pasted everything as You wrote but my beingHandled bool instantly changes to true (it is not waiting 3 seconds)
     
  43. Shack_Man

    Shack_Man

    Joined:
    Jun 7, 2017
    Posts:
    365
    That's what it's supposed to do: Whenever it gets switched to true, it switches back to false after 3 seconds.

    P.S. I can scratch "posting in a 10 year old thread" of my unity bucket list now, but I assume you had that problem today :)
     
  44. EnesBueke

    EnesBueke

    Joined:
    Feb 4, 2021
    Posts:
    2
    Still funny in CoronaTimes
     
  45. EnesBueke

    EnesBueke

    Joined:
    Feb 4, 2021
    Posts:
    2
    Dude, you're still saving lives.... Thank you!
     
  46. tmarlok

    tmarlok

    Joined:
    Feb 24, 2020
    Posts:
    6
    perfectly works in my project, Thank you:
    Code (csharp):
    1.  
    2.  public void Update()
    3.     {
    4.         if (!beingHandled)
    5.         {
    6.             StartCoroutine(DataRequest());
    7.         }
    8.     }
    9.  
    10.     private IEnumerator DataRequest()
    11.     {
    12.         beingHandled = true;
    13.         // process pre-yield
    14.         yield return new WaitForSeconds(30.0f);
    15.         // process post-yield
    16.         StartCoroutine(RestClient.Instance.Get(WEB_URL, HandleResult));
    17.         beingHandled = false;
    18.  
    19.         void HandleResult(OpenSkyResult result)
    20.         {
    21.  
    22.             foreach (OpenSkyState state in result.states)
    23.             {
    24.                 GameObject plane = Instantiate(planePrefab) as GameObject;
    25.                 LatLon2Unity planeScript = plane.GetComponent<LatLon2Unity>();
    26.                 planeScript.areaRight = ctpd.areaRight;
    27.                 planeScript.areaLeft = ctpd.areaLeft;
    28.                 planeScript.areaTop = ctpd.areaTop;
    29.                 planeScript.areaBottom = ctpd.areaBottom;
    30.                 planeScript.areaWidth = ctpd.areaWidth;
    31.                 planeScript.areaLength = ctpd.areaLength;
    32.                 planeScript.destinationLat = state.latitude;
    33.                 planeScript.destinationLon = state.longitude;
    34.             }
    35.         }
    36.     }
    37. }
    38.  
     
Thread Status:
Not open for further replies.