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

Best way to call an IEnumerator from a static method in Unity with C#

Discussion in 'Scripting' started by TK_Development, Jun 30, 2020.

  1. TK_Development

    TK_Development

    Joined:
    Mar 10, 2019
    Posts:
    6
    Editor: Unity - C#

    can you give me some informations and tipps how i can start an IEnumerator from a static method. What I know so far are the following options:

    A): Make the Method (METHOD_1) that calls the IEnumerator non static and then search the script like this

    Code (CSharp):
    1. FindObjectOfType<Scriptname>().METHOD_1();
    B): Use MonoBehaviour to start the Coroutine

    Code (CSharp):
    1. Scriptname.METHOD_1(this);
    Code (CSharp):
    1. public static void METHOD_1(MonoBehaviour StartThisStatic)
    2. {
    3.    StartThisStatic.StartCoroutine(Test());
    4. }
    5. public static IEnumerator Test()
    6. {
    7.    yield return new WaitForSeconds(2f);
    8. }
    C): Use instance in awake/start

    What is the best option in terms of performance and stability? Can you explain a little background knowledge to me in a simple way?

    Thank you very much!

    EDIT:
    My solution was to create a Singleton CoroutineManager and call the Coroutines with it.
    Here is the link for the original post:
    https://stackoverflow.com/questions...or-from-a-static-method-in-unity-with-c-sharp
     
    Last edited: Jun 30, 2020
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,963
    This is a way to do it, if you want a coroutine to live through scene changes. However, just beware that a singleton will persist indefinitely, which means if you change scenes and a coroutine is still running, Unity could easily just Destroy() all the parts you were accessing in the coroutine, making your program crash with a null reference.

    Instead, I like to put my coroutine runner script, one GameObject per running Coroutine usually, right there in the scene with everything else. When I change scenes, EVERYTHING dies, including the coroutines, which is 99.9% of the time what I want.
     
  3. TK_Development

    TK_Development

    Joined:
    Mar 10, 2019
    Posts:
    6

    Hey thank you for your reply!
    You are absolutely right.
    And what if I remove the DontDestroyOnLoad(_singleton) and call the CoroutineManager/Initialize Method every time I load a scene?
    Would that completely destroy the running coroutine when switching a scene?

    I tested it and it worked but does that make sense at all in this way or can it still cause errors in special cases?
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,963
    When I need to run a coroutine and don't have the relevant Monobehavior handy (such as from a static function), I have a little runner MonoBehavior with a static factory function, and it takes an IEnumerator, which it then runs on your behalf.

    It creates a fresh GameObject, adds itself to it, injects the IEnumerator reference, and then in the Start() function it runs that Coroutine.

    The static factory function also returns the GameObject that it produced (one coroutine per GameObject), so sometimes if I want something to persist across scenes, I would take that returned value and call DontDestroyOnLoad() on it. Or alternately I can destroy it too!

    I don't have that script handy, but here's what I mean by a factory pattern with a monobehavior:

    Factory Pattern in lieu of AddComponent (for timing and dependency correctness):

    https://forum.unity.com/threads/understanding-delays-in-unity.914870/#post-5997281

    I would have a Create() method for this little coroutine runner maker thingy.