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

How to write Coroutines inside of classes

Discussion in 'Scripting' started by elmar1028, Nov 21, 2016.

  1. elmar1028

    elmar1028

    Joined:
    Nov 21, 2013
    Posts:
    2,353
    Hey guys,

    As the title says, how do I write coroutines inside of class (note they're not MonoBehavior). Is there a way to approach this kind of problem?

    Thanks! :)
     
  2. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    You can create them but a MonoBehaviour instance is required to run them. You can run Coroutines not included in the MonoBehaviour that is running them by creating a method that takes an IEnumerator

    Code (csharp):
    1.  
    2. public class CoRunner : MonoBehaviour
    3. {
    4.     public static CoRunner Instance { get; private set; }
    5.  
    6.     void Awake()
    7.     {
    8.         Instance = this;
    9.     }
    10.  
    11.     public void Run(IEnumerator cor)
    12.     {
    13.         StartCoroutine(cor);
    14.     }
    15. }
    16.  
    17. public class AnotherClass
    18. {
    19.     void Foo()
    20.     {
    21.         CoRunner.Instance.Run(Do());
    22.     }
    23.  
    24.     IEnumerator Do()
    25.     {
    26.         yield return new WaitForSeconds(3);
    27.         Debug.Log("Done!");
    28.     }
    29. }
    30.  
     
    Ryiah and elmar1028 like this.
  3. elmar1028

    elmar1028

    Joined:
    Nov 21, 2013
    Posts:
    2,353
    Thank you! This seemed to fix the problem.

    Also, is this a commonly used practice? Does it affect overall performance in any way?
     
  4. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Yes.

    No.

    It's also worth noting that you don't need the wrapper method at all since StartCoroutine is public. So you could technically do this
    Code (csharp):
    1.  
    2. CoRunner.Instance.StartCoroutine(Do());
    3.  
    I like to encapsulate the behavior though.
     
    Ryiah and elmar1028 like this.
  5. elmar1028

    elmar1028

    Joined:
    Nov 21, 2013
    Posts:
    2,353
    This is gold! Thank you once again :D
     
  6. Dameon_

    Dameon_

    Joined:
    Apr 11, 2014
    Posts:
    542
    It's actually more efficient in some ways to have lots of non-MonoBehaviour classes that use a single in-game object to run any in-scene code that's needed. I have a standard singleton that I plug in to projects which I use for injecting threaded output into Unity's thread. I use delegates and events for this purpose, which means there is some allocations and thus garbage (can't wait for the new garbage collector), but there is a performance impact to Unity's "magic" methods (Update and such),

    Of course, you don't want to do all of your processing this way, but my profiler results have been impressive, and I haven't even begun taking real advantage of the multi-threading options this opens up.
     
    nathank000 likes this.
  7. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Coroutines are part of MonoBehaviour. So they cannot run without a MonoBehaviour. You have to do something like @KelsoMRK suggested and run them on a MonoBehaviour. If you go this route, I would actually suggest doing lazy instantiation with static methods.

    I would also caution that excessive use of coroutines can lead to messy and difficult to follow code. Tread carefully, before you go starting a coroutine on random objects, think if you really need it, or if there is a better way to complete your task.
     
    Ryiah likes this.
  8. Dameon_

    Dameon_

    Joined:
    Apr 11, 2014
    Posts:
    542
    Seconded. About the only time I use a coroutine is when I need a loading screen.