Search Unity

Do I need to stop a coroutine when it is finished?

Discussion in 'Scripting' started by Rusoski, Aug 18, 2017.

  1. Rusoski

    Rusoski

    Joined:
    Nov 6, 2013
    Posts:
    63
    So I got this init code:

    Code (CSharp):
    1.  
    2. IEnumerator _IEnumeratorClearSections = ClearSections();
    3.     bool stopIEnumeratorClearSections = false;
    4.  
    At some point:

    Code (CSharp):
    1. StartCoroutine(_IEnumaratorClearSections);
    Then this one inside void Update(){}

    Code (CSharp):
    1. if (stopIEnumeratorClearSections)
    2.         {
    3.             StopCoroutine(_IEnumeratorClearSections);
    4.             _IEnumeratorClearSections = ClearSections();
    5.             stopIEnumeratorClearSections = false;
    6.         }
    And finaly the IEnumarator it self:

    Code (CSharp):
    1. IEnumarator ClearSections()
    2.     {
    3.         while (something)
    4.         {
    5.             yield return null;
    6.         }
    7.     stopIEnumeratorClearSections = true;
    8.     }
    Is that correct or the coroutine stops automatically once the while loop is complete and it gets out of the ClearSections(){} method?
     
    Last edited: Aug 18, 2017
    D12294 likes this.
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,187
    A coroutine is just like a method except that you can yield in it. (not counting the stopping and how you call it).

    So if you mentally take the yield out, just ask yourself, will this coroutine ever end by reaching the last line in it. If so, you don't need to stop it.
     
  3. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,521
    Code (csharp):
    1.         public bool IsAlive; // play, watch health, and click this at some point.
    2.         public float Health;
    3.  
    4.         public void Start()
    5.         {
    6.             // Create the coroutine.
    7.             StartCoroutine(HealthTicker());
    8.         }
    9.  
    10.         public void Update()
    11.         {
    12.             // No maintenance on the coroutine.
    13.         }
    14.  
    15.         public IEnumerator HealthTicker()
    16.         {
    17.             // It will be stuck here until IsAlive == false.
    18.             while (IsAlive)
    19.             {
    20.                 Health += Time.deltaTime * 5;
    21.                 yield return null; // This simply makes it yield until the next frame where it will then loop back into this while statement.
    22.             }
    23.  
    24.             // When IsAlive is false, it drops out of the while loop and can reach the end of it's code.
    25.             Debug.Log("I have perished, and thus my coroutine has run it's course.", this);
    26.         }
    When you start a coroutine it will do whatever you tell it and obey the yield instructions you give it forever. If a coroutine instance reaches the end of it's code then it automatically goes away forever.

    In the above example the coroutine is basically a waste of resources because you could easily do this:

    Code (csharp):
    1.         public bool IsAlive;
    2.         public float Health;
    3.  
    4.         public void Start()
    5.         {
    6.  
    7.         }
    8.  
    9.         public void Update()
    10.         {
    11.             if (IsAlive) RegenHealth();
    12.         }
    13.  
    14.         public void RegenHealth()
    15.         {
    16.             Health += Time.deltaTime * 5;
    17.         }
    So be mindful and only use them if they can't be replaced by simpler approaches.
     
    honor0102 likes this.
  4. Rusoski

    Rusoski

    Joined:
    Nov 6, 2013
    Posts:
    63
    Thank you!

    I al using IEnumerators because I work with a huge amount of data taken from a Data Base, so I need to somehow use that data to set properties to the game objects, so I yield return null every 1000 loops and end when the iteration goes trough the whole list. If there is a better option for this I take it, problem is that I can not access to GameObject properties, components, instances, transforms and anything from a separed thread, so I load data from hte Data Base into Unity on a separated Thread, then I use IEnumarators to asign that data to the game objects (data has about 14 columns and 20k rows, this can go up to 1kk rows)
     
  5. BlackPete

    BlackPete

    Joined:
    Nov 16, 2016
    Posts:
    970
    You don't have to use StartCoroutine if you want more flexibility on what to do with the iterator. You can always call MoveNext() yourself whenever you want it to iterate.

    But, yes, in order to access the Unity API, it must be done from the main thread.

    You'll have to use some kind of a thread safe container that can be shared between the main thread and other threads. You can actually design for this -- have the main thread check if there's new data in the container, then act accordingly on it and update the UI.
     
    Kiwasi likes this.
  6. Rusoski

    Rusoski

    Joined:
    Nov 6, 2013
    Posts:
    63
    Unity is not thread-friendly, that sucks...
     
  7. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,521
    Threads aren't friendly.
     
    ericbegue, Ryiah and Kiwasi like this.
  8. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Sure it is. You can spin as many threads as you like. You just have to interact with Unity through the main thread. It's actually a pretty decent way to keep things safe.

    Threading is nasty business at the best of times. You would not like it if Unity called your code from multiple threads, or if you could call into Unity from multiple threads.

    As to the OP question, a coroutine will stop automatically if it runs out of code to execute, or if the MonoBehaviour it is on is disabled/destroyed.
     
    Ryiah likes this.
  9. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Small edit: Disabling a monobehaviour does not stop a coroutine. :)
     
    florianBrn and Kiwasi like this.
  10. Rusoski

    Rusoski

    Joined:
    Nov 6, 2013
    Posts:
    63
    Thank you guys for all your responces, I have managed the read the info only if the thread has finished it's job, but My main questions is still here, do I have to stop a Coroutune when it is finished or it stops by itself one finished?
     
  11. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    If it will reach the end of the function, it stops itself because it's done. It naturally concludes like any other function. If it's running a loop with no end condition, you need to stop it manually with StopCoroutine.
     
  12. Rusoski

    Rusoski

    Joined:
    Nov 6, 2013
    Posts:
    63
    Thank you, that is what I wanted to hear
     
    lmraddmb likes this.