Search Unity

  1. Get all the Unite Berlin 2018 news on the blog.
    Dismiss Notice
  2. Unity 2018.2 has arrived! Read about it here.
    Dismiss Notice
  3. We're looking for your feedback on the platforms you use and how you use them. Let us know!
    Dismiss Notice
  4. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  5. Improve your Unity skills with a certified instructor in a private, interactive classroom. Learn more.
    Dismiss Notice
  6. ARCore is out of developer preview! Read about it here.
    Dismiss Notice
  7. Magic Leap’s Lumin SDK Technical Preview for Unity lets you get started creating content for Magic Leap One™. Find more information on our blog!
    Dismiss Notice
  8. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

C# Coroutines in static functions

Discussion in 'Scripting' started by meeydoo, May 2, 2012.

  1. meeydoo

    meeydoo

    Joined:
    Apr 8, 2012
    Posts:
    28
    Code (csharp):
    1. public class A : Monobehaviour
    2. {
    3. IEnumerator Wait()
    4. {
    5. yield return new WaitForSeconds(5);
    6. Debug.Log("blabla");
    7. }
    8.  
    9. public static void DoSomething()
    10. {
    11. StartCoroutine(Wait());  // not possible ?
    12.  
    13. }
    14. public class B : Monobehavior
    15. {
    16.  
    17. void Start()
    18. {
    19. A.DoSomething();
    20. }
    21.  
    22. }
    23.  
    So I'm not allowed to start Coroutines in static functions ? Is there a work around ?
     
  2. flaminghairball

    flaminghairball

    Joined:
    Jun 12, 2008
    Posts:
    865
    It is indeed impossible. The workaround is to turn it into an instance method, and just pipe the static call into your instance. For example

    Code (csharp):
    1.  
    2. public class StaticCoroutine : MonoBehaviour{
    3.  static public StaticCoroutine instance; //the instance of our class that will do the work
    4.  
    5.  void Awake(){ //called when an instance awakes in the game
    6.   instance = this; //set our static reference to our newly initialized instance
    7.  }
    8.  
    9.  IEnumerator PerformCoroutine(){ //the coroutine that runs on our monobehaviour instance
    10.   while(true){
    11.    yield return 0;
    12.   }
    13.  }
    14.  
    15.  static public void DoCoroutine(){
    16.   instance.StartCoroutine("PerformCoroutine"); //this will launch the coroutine on our instance
    17.  }
    18. }
    Now you can call StaticCoroutine.DoCoroutine(). Make sure you drop the StaticCoroutine on an object in your scene or you won't have an instance and you'll get a NullReferenceException.
     
    shough, Laiken, Mycroft and 2 others like this.
  3. kingcharizard

    kingcharizard

    Joined:
    Jun 30, 2011
    Posts:
    1,137
    I thought to use static functions you needed to make the class static too... or is that wrong?
     
  4. grim2594

    grim2594

    Joined:
    Nov 5, 2010
    Posts:
    104
    You use static when you don't want to create an instance of a class object. The OP is stating that he can't use coroutines in a static method.

    The only other alternative is to create a class instance, and then execute the method from that instance.

    Code (csharp):
    1. class corout { public void doCor() { // do something } }
    2.  
    3. corout newInstance = new corout();
    4. newInstance.doCor();
     
  5. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,443
    Only make a class static if you NEVER want an instance of it. If a class is static then all members and methods must also be static, but not the other way around.
     
    Laiken and Mycroft like this.
  6. szi_John

    szi_John

    Joined:
    Feb 10, 2012
    Posts:
    70
    There is a tutorial video you can find on youtube (or through google) for writing a coroutine manager as well as the proper singleton pattern for Unity.
     
  7. brunoleos

    brunoleos

    Joined:
    May 14, 2014
    Posts:
    30
    If you don't want a singleton (because your code can become very dependent on them, which makes it difficult to refactor) nor using dummy GameObjects (because you have to create/manage them), you can pass a MonoBehaviour as argument to your static method, and them call StartCoroutine from it.

    If you call the static method from a script (Monobehaviour-based object attached to GameObject), you can call the static method using the "this" keyword:

    Example static method:
    Code (CSharp):
    1.     public class Utility
    2.         {
    3.             public static void mysql_query(string sServer, string sQuery, MonoBehaviour justToStartCoroutine)
    4.             {
    5.                 sQuery = WWW.EscapeURL(sQuery);
    6.                 www = new WWW(sServer + "?Query=" + sQuery);
    7.                 justToStartCoroutine.StartCoroutine(WaitForRequest(www));
    8.                 if(www.error == null)
    9.                 {
    10.                     ResultSet = www.text;
    11.                 }
    12.                 else
    13.                 {
    14.                     Debug.Log("Error at: " + www.error);
    15.                 }
    16.             }
    17.         }
    Example call at YourScript.cs:
    Code (CSharp):
    1. public class YourScript : MonoBehaviour
    2.         {
    3.     // Class members
    4.  
    5.             void Start()
    6.             {
    7.                 Utility.mysql_query("", "", this);
    8.             }
    9.         }
     
    RodrigoSeVeN likes this.
  8. Trinary

    Trinary

    Joined:
    Jul 26, 2013
    Posts:
    328
    If you use MEC then there are no longer any issues with starting coroutines from static functions/classes or outside of MonoBehaivour classes.

    (MEC is a free plugin)
     
    Last edited: Jun 17, 2018
  9. CykesDev

    CykesDev

    Joined:
    Feb 15, 2018
    Posts:
    3
    To make life easier with static methods and coroutines, I created a class called StaticCoroutine that allows the user to fire coroutines in static methods with an internally stored, privately managed instance. The script requires no scene dependencies, so no need to add the monobehaviour script to a GameObject (unless you want to). To use, simply create a C# Script named "StaticCoroutine" and paste the following code in the script:

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using UnityEngine;
    4.  
    5. public class StaticCoroutine : MonoBehaviour {
    6.     private static StaticCoroutine m_instance;
    7.  
    8.     // OnDestroy is called when the MonoBehaviour will be destroyed.
    9.     // Coroutines are not stopped when a MonoBehaviour is disabled, but only when it is definitely destroyed.
    10.     private void OnDestroy()
    11.     { m_instance.StopAllCoroutines(); }
    12.  
    13.     // OnApplicationQuit is called on all game objects before the application is closed.
    14.     // In the editor it is called when the user stops playmode.
    15.     private void OnApplicationQuit()
    16.     { m_instance.StopAllCoroutines(); }
    17.  
    18.     // Build will attempt to retrieve the class-wide instance, returning it when available.
    19.     // If no instance exists, attempt to find another StaticCoroutine that exists.
    20.     // If no StaticCoroutines are present, create a dedicated StaticCoroutine object.
    21.     private static StaticCoroutine Build() {
    22.         if (m_instance != null)
    23.         { return m_instance; }
    24.  
    25.         m_instance = (StaticCoroutine)FindObjectOfType(typeof(StaticCoroutine));
    26.  
    27.         if (m_instance != null)
    28.         { return m_instance; }
    29.  
    30.         GameObject instanceObject = new GameObject("StaticCoroutine");
    31.         instanceObject.AddComponent<StaticCoroutine>();
    32.         m_instance = instanceObject.GetComponent<StaticCoroutine>();
    33.  
    34.         if (m_instance != null)
    35.         { return m_instance; }
    36.  
    37.         Debug.LogError("Build did not generate a replacement instance. Method Failed!");
    38.  
    39.         return null;
    40.     }
    41.  
    42.     // Overloaded Static Coroutine Methods which use Unity's default Coroutines.
    43.     // Polymorphism applied for best compatibility with the standard engine.
    44.     public static void Start(string methodName)
    45.     { Build().StartCoroutine(methodName); }
    46.     public static void Start(string methodName, object value)
    47.     { Build().StartCoroutine(methodName, value); }
    48.     public static void Start(IEnumerator routine)
    49.     { Build().StartCoroutine(routine); }
    50. }
    51.  
    I preferred this method over using Awake because I only query the instance whenever I need it. Whenever I don't have an actively-loaded instance, I can find another one (should it exist), or even dynamically create a blank GameObject with the needed script. This is why no scene alterations are needed, and that the code is simply plug and play.
     
  10. unbi

    unbi

    Joined:
    Aug 15, 2017
    Posts:
    1
    Thanks a lot! Works like a charm,
     
    CykesDev likes this.
  11. IWannaTaco

    IWannaTaco

    Joined:
    Jan 19, 2015
    Posts:
    7

    Plug in and Play? So instead I should use

    StaticCoroutine.Start(BLAH);

    or is there something else? Because I made a script and did that and still get the non-static member error
     
  12. CykesDev

    CykesDev

    Joined:
    Feb 15, 2018
    Posts:
    3
    You have to create a C# Script named StaticCoroutine.cs. Inside of that script, clear everything you see, then copy and paste my code into it. Once that's done, go into any other C# Script and use:

    StaticCoroutine.Start("methodName");


    Could you please provide more information about the error? I'd like to know where it's occurring, and if any other errors are present.
     
    Algal likes this.
  13. LukeNukem44

    LukeNukem44

    Joined:
    Sep 2, 2015
    Posts:
    7
    That's a bit hard to read.
     
  14. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    312
    It's a computer program.
     
  15. LukeNukem44

    LukeNukem44

    Joined:
    Sep 2, 2015
    Posts:
    7
    And?
    I could rewrite his code to be readable, like flaminghairball did.
    Get off the drugs, idiot. I said, it's hard to read.
    My bet is you're a computer program.
     
  16. TaleOf4Gamers

    TaleOf4Gamers

    Joined:
    Nov 15, 2013
    Posts:
    725
    It is not more readable (apart from the indentation), it just works which is the whole point of this thread.

    Wow, this is supposed to be a professional environment and it seems Owen was stating that code always looks this way.

    I cant even...
     
  17. santiagolopezpereyra

    santiagolopezpereyra

    Joined:
    Feb 21, 2018
    Posts:
    20
    I know this is not the most interesting reply, but that code is so cool. Thanks.
     
  18. CykesDev

    CykesDev

    Joined:
    Feb 15, 2018
    Posts:
    3
    Thankies! Glad my code helped. :)
     
  19. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,443
    Three posts into your tenure here.....way to make a good impression....