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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Coroutine Question - Can you combine WaitForSeconds with a condition?

Discussion in 'Scripting' started by Fishypants, Oct 5, 2011.

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

    Fishypants

    Joined:
    Jan 25, 2009
    Posts:
    444
    So what I am trying to do is have a coroutine run for either "X" amount of seconds and terminate, or terminate early when a button is pressed. Is there a way to mix WaitForSeconds and also check for a button press or is this a case of having to implement my own timer?

    Trying to wrap my head around coroutines. If anyone has some insight or can point me in the right direction it would be much appreciated. Thanks!
     
  2. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Code (csharp):
    1.  
    2. public bool runCoroutine = true;
    3.  
    4. void Start()
    5. {
    6.      StartCoroutine(Foo());
    7. }
    8.  
    9. void Update()
    10. {
    11.     if (Input.GetKey("whatever key you want")
    12.     {
    13.         runCoroutine = false;
    14.     }
    15. }
    16.  
    17. public IEnumerator Foo()
    18. {
    19.     while (runCoroutine)
    20.     {
    21.         // do stuff here
    22.     }
    23. }
    24.  
    Or alternately, a similar pattern but using StopCoroutine instead.
     
  3. bdev

    bdev

    Joined:
    Jan 4, 2011
    Posts:
    656
    you can't do it with WaitForSeconds but you can do it with a coroutine.

    Code (csharp):
    1.  
    2. bool bDone;
    3.  
    4. IEnumerator WaitForDoneProcess( float timeout ){
    5.     while(!bDone) {
    6.         yield return null;
    7.         timeout -= Time.deltaTime;
    8.         if( timeout <= 0f ) break;
    9.     }
    10. }
    11.  
    12. YieldInstruction WaitForDone( float timeout ) { return StartCoroutine(WaitForDoneProcess(timeout)); }
    13.  
    then you would just replace parts of the code above where it says bDone with whatever condition you're waiting for.

    Then in your couroutine you would just do the following:

    Code (csharp):
    1.  
    2. IEnumerator Start() {
    3.     // instead of wait for seconds use the above
    4.     yield return WaitForDone( 2f );// wait for done or 2 seconds, whichever comes first.
    5.     if( bDone ) { /* done code here */ }
    6.     else { /* not done code here */ }
    7. }
    8.  
     
    sirshelley and lucbloom like this.
  4. U7Games

    U7Games

    Joined:
    May 21, 2011
    Posts:
    943
    In addition, you can use yield inside an update... but only declaring an extra function :

    Code (csharp):
    1.  
    2.  
    3. function Update(){
    4. MakeThis();
    5. }
    6.  
    7. function MakeThis(){
    8. //make this first thing
    9. yield WaitForSeconds(2)
    10. //make the second thing..
    11. }
    12.  
     
  5. Fishypants

    Fishypants

    Joined:
    Jan 25, 2009
    Posts:
    444
    Awesome! Thanks for the info guys. I had a feeling it would be as how BDev is describing, where you'd have to keep track of the time thats passed yourself. Cool, well thats good to know, thank you!
     
  6. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    That won't work, because it will start a new instance of MakeThis every frame. What BDev said is the way to go.

    --Eric
     
    Bunny83 and kalibcrone like this.
  7. hexaJer

    hexaJer

    Joined:
    Aug 26, 2018
    Posts:
    7
    8 years later... :D

    Code (CSharp):
    1. private bool _readyForQuit;
    2.  
    3. private IEnumerator WaitForQuit(float timeout)
    4. {
    5.     yield return new WaitForSeconds(timeout);
    6.     yield return new WaitUntil(() => _readyForQuit);
    7.     Application.Quit;
    8. }
    9.  
    10. private void ReadyForQuit()
    11. {
    12.     _readyForQuit = true;
    13. }
    14.  
    15. // Usage :
    16. StartCoroutine(WaitForQuit(2));
    17.  
     
    ssloppi97 likes this.
  8. moji_kashani

    moji_kashani

    Joined:
    Mar 10, 2020
    Posts:
    2
    9 years later... ;)

    Code (CSharp):
    1. public sealed class WaitForDone : CustomYieldInstruction
    2. {
    3.     private Func<bool> m_Predicate;
    4.     private float m_timeout;
    5.     private bool WaitForDoneProcess()
    6.     {
    7.         m_timeout -= Time.deltaTime;
    8.         return m_timeout <= 0f || m_Predicate();
    9.     }
    10.  
    11.     public override bool keepWaiting => !WaitForDoneProcess();
    12.  
    13.     public WaitForDone(float timeout, Func<bool> predicate)
    14.     {
    15.         m_Predicate = predicate;
    16.         m_timeout = timeout;
    17.     }
    18. }
    19.  
    20. // Usage
    21. yield return new WaitForDone(timeout, ()=> condition);
    22.  
     
  9. lgmontoya

    lgmontoya

    Joined:
    Dec 31, 2020
    Posts:
    2
    Better late than never ... :)
    I probably only understand 90% of your solution, but works perfectly with your example usage. I am using it and it works.
     
Thread Status:
Not open for further replies.