Search Unity

Why does this Coroutine only run once?

Discussion in 'Scripting' started by Deleted User, Aug 29, 2015.

  1. Deleted User

    Deleted User

    Guest

    "Something" is only printed once...

    Code (CSharp):
    1. IEnumerator printSomething;
    2.  
    3. void Start () {
    4.  
    5.     printSomething = PrintSomething();
    6.     StartCoroutine (printSomething);
    7.  
    8. }
    9.  
    10. IEnumerator PrintSomething () {
    11.  
    12.     print ("Something");
    13.  
    14.     yield return null;
    15.     StartCoroutine (printSomething);
    16.  
    17. }
     
  2. Deleted User

    Deleted User

    Guest

    I only can quess.
    I think the problem is that the compiler generates a class for your PrintSomething Method wich implements the IEnumerator interface.
    In this class is basically a state maschine. When ever MoveNext() is called on the interface the state advances to its next possible state. When you reach the code after your last yield, the state is set to its last possible value.
    That means that MoveNext returns false and the execution of this method is not possible anymore.

    without testing you could try to call the Reset method on your printSomething member.

    Code (CSharp):
    1. IEnumerator printSomething;
    2.  
    3. void Start () {
    4.  
    5.     printSomething = PrintSomething();
    6.     StartCoroutine (printSomething);
    7.  
    8. }
    9.  
    10. IEnumerator PrintSomething () {
    11.  
    12.     print ("Something");
    13.  
    14.     yield return null;
    15.     printSomething.Reset();
    16.     StartCoroutine (printSomething);
    17.  
    18. }
     
  3. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,532
    The problem you're having is you think the IEnumerator.Reset for iterator functions actually resets the function.

    But it doesn't.

    From the documentation:
    https://msdn.microsoft.com/en-us/library/dscyy5s0.aspx

    So when you call StartCoroutine on the iterator you created, it's already spent, and StartCoroutine just stops immediately.

    You must call PrintSomething() to get a new iterator to enumerate over.
     
    Kiwasi and Deleted User like this.
  4. Deleted User

    Deleted User

    Guest

    Thank you, @element_wsc, that clears up the inner workings. I tried calling Reset(), however it does throw an error.

    Logically, that's what I observed, however thank you for the explanation.
     
  5. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    You could get the desired behaviour by storing the method call as a delegate rather then an IEnumerator.

    I am curious what the use case for this was.