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. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Use Coroutine After "yield break" !?

Discussion in 'Scripting' started by AhmadIssawi, Jul 6, 2018.

  1. AhmadIssawi

    AhmadIssawi

    Joined:
    Jun 4, 2016
    Posts:
    48
    Hi every body...
    i want to Use a Coroutine again, after using it a first time and reaching its "yield break" .....
    in fact, here is my code :

    Code (CSharp):
    1. void Start(){
    2. //print("Start() Called...");
    3. MyCoroutine = PrintHello();
    4. }
    5.  
    6. public void BtnPrsd(){
    7. print("BtnPrsd() is Called...");
    8. StartCoroutine(MyCoroutine);
    9. }
    10.  
    11. IEnumerator PrintHello()
    12. {print("PrintHello() Called...");
    13. for(int i=1; i<=5; i++)
    14. {print("Hello....!");
    15. yield return new WaitForSeconds(1);
    16. }
    17. // Do Something...
    18. yield break;
    19. }
    a Button is related to the function BtnPrsd(), so it call this later each time the Button is Pressed...
    i Need to :
    Press the Button and get the typing 5 times and Do Something after that ....
    and after a while, press the Button again and get the typing another time and Do Something ... and so ...
    the Problem is : whenever "yield break" is reached, the Coroutine is KILLED, and we can No longer using it....
    Thanks for any help ...
     
    Last edited: Jul 6, 2018
  2. FernandoHC

    FernandoHC

    Joined:
    Feb 6, 2018
    Posts:
    333
    You should put your code inside a while loop if you don' want it to end.
    Side note, please consider using a more common type of indentation on your code, or whenever you post it, as it helps a lot the reader to understand faster.
     
    AhmadIssawi likes this.
  3. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    817
    Please format your code properly.
     
    carking1996 and AhmadIssawi like this.
  4. AhmadIssawi

    AhmadIssawi

    Joined:
    Jun 4, 2016
    Posts:
    48
    Thank you All...
    Dear FernandoHC,
    it is not a problem of the loop kind....
    even if i write :

    Code (CSharp):
    1. IEnumerator PrintHello()
    2. {while(true)
    3. {print("Hello....!"); i++;
    4. if(i>=5)
    5. {//Do something...
    6. yield break;}
    7. yield return new WaitForSeconds(1);
    8. }
    i will get the same problem ....
    the problem -as i explained well above- is that whenever "yield break" is reached, the Coroutine is KILLED, and we can No longer use it....
    the System understand the "yield break" as : KILL Coroutine !

    Thanks for any help ...
     
  5. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,292
    @AhmadIssawi
    If you want to just continue the loop, but return the control, you can do the following:
    Code (CSharp):
    1. while (true) {
    2.    ...
    3.    if (...) {
    4.         yield return null; // Can be any Wait
    5.         continue;
    6.    ]
    7. }
    Order is important. If you call continue before the yield statement, you'll hang your thread until other yield statement will be reached.
     
    AhmadIssawi likes this.
  6. AhmadIssawi

    AhmadIssawi

    Joined:
    Jun 4, 2016
    Posts:
    48
    Dear VergiUa,
    First : Thank you for your help...
    Next : Your code does Not STOP the Coroutine, it only goes to the next iteration by using continue statement ...
    Let me explain again the Point :
    When the user clicks a Button, the program write in the console "Hello....!" five times, and then Does something and Stops ....
    We want that each time the user clicks the Button, the program does the same effects ....
    (Maybe the user will click after 10 minutes, maybe other ....)

    So, the problem now is clear : Coroutine is Unable to be used a second time after being stopped by its "yield break"...
    am i right ??

    or there is a way to use the Coroutine many times even if its "yield break" is reachable ??!

    Many thanks...:rolleyes:
     
  7. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    yield break ends the coroutine. If you want to run it again, use StartCoroutine(function) again.
     
    AhmadIssawi likes this.
  8. BlackPete

    BlackPete

    Joined:
    Nov 16, 2016
    Posts:
    970
    The main point is if you want to keep using the coroutine, don't let it exit. Use a loop instead.

    So, yes, once you use "yield break", you are saying you want this coroutine to die. Once it dies, you can't re-use it. You'll have to start a new one.

    So either let it die, or don't let it die in the first place.
     
    ilmario, AhmadIssawi and xVergilx like this.
  9. AhmadIssawi

    AhmadIssawi

    Joined:
    Jun 4, 2016
    Posts:
    48
    YES, But that is exactly what i do ... each time the user Presses the button, the function BtnPrsd() is called, and it Makes the StartCoroutine() :

    Code (CSharp):
    1. public void BtnPrsd(){
    2. print("BtnPrsd() is Called...");
    3. StartCoroutine(MyCoroutine);
    4. }
    BUT Nothing Happened !!!! (the Coroutine does NOT start again...)
     
  10. AhmadIssawi

    AhmadIssawi

    Joined:
    Jun 4, 2016
    Posts:
    48
    Not in any way ?? even using StartCoroutine() or like ???


    How ??
     
  11. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Make sure you start the coroutine with the method instead of the variable.
    Code (csharp):
    1. StartCoroutine(PrintHello());
     
    Ryiah and AhmadIssawi like this.
  12. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    Oh, what's happening is that you're storing the result of the IEnumerator inside of MyCoroutine at Start(). You don't want to do that, as it holds onto the exact enumerator of the original coroutine -- so yes, it will never run again properly because you're telling it to run from the previous result.

    Do something like this instead:
    Code (csharp):
    1.  
    2.        Coroutine MyCoroutine = null; // change your MyCoroutine declaration
    3.  
    4.        public void BtnPrsd()
    5.        {
    6.            print("BtnPrsd() is Called...");
    7.  
    8.            if(MyCoroutine == null) // only run when the previous result has finished
    9.                MyCoroutine = StartCoroutine(PrintHello());
    10.        }
    11.  
    12.        IEnumerator PrintHello()
    13.        {
    14.            print("PrintHello() Called...");
    15.            for (int i = 1; i <= 5; i++)
    16.            {
    17.                print("Hello....!");
    18.                yield return new WaitForSeconds(1);
    19.            }
    20.            // Do Something...
    21.  
    22.            MyCoroutine = null; // clear it before we end the coroutine
    23.  
    24.            yield break;
    25.        }
    26.  
    I missed that because you left its declaration out of your code. Next time try to post complete code when getting help so this sort of error is easier to find.
     
  13. AhmadIssawi

    AhmadIssawi

    Joined:
    Jun 4, 2016
    Posts:
    48
    WOW .... Excellent Answer ... a Big "Thank you" Really !!
    Now, i understand what happened with me last 2 weeks :)...

    Just a very small problem in your code ....
    when i we write :
    MyCoroutine = StartCoroutine(PrintHello());

    the compiler gives the following error :

    Cannot implicitly convert type `UnityEngine.Coroutine' to `System.Collections.IEnumerator'
     
  14. AhmadIssawi

    AhmadIssawi

    Joined:
    Jun 4, 2016
    Posts:
    48
    YES, thank you very much dear ....:)
     
  15. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Change the type of 'MyCoroutine', as @GroZZleR showed, to 'Coroutine'.
     
    Warnau and AhmadIssawi like this.