0

this is my first big game project for Unity, and im trying to achieve using static methods calling coroutines to change game state and load levels with update calls in between.

from what i have read something like this would work?

public class Game : MonoBehaviour {

  private static Game me = null;

  private IEnumerator LoadMap(int sceneIndex)
  {
    /*change game state to loading*/
    yield return null;
    Application.LoadLevel(sceneIndex);
    yield return null;
    /*change game state to playing*/
  }

  public static void StartNewGame()
  {
    /*settup new game*/
    me.StartCoroutine(me.LoadLevel(1));
  }

  void Awake()
  {
    me = this;
  }

}

i have had to rewrite stuff a couple times so i thot i would just take a break and ask ahead this time.

ninjagear
  • 1
  • 3
  • Presumably it's not working in some way, so maybe a clue as to what it's doing you don't want it doing or not doing you do want it doing? – blm Nov 12 '15 at 19:29
  • using this method required me to rewrite other crap and i was kinda short on time when i made this post. so i thot i would ask before i did tested it and made the changes to possibly avoid rolling back. but it all works great thanks for the reply – ninjagear Nov 24 '15 at 01:09

1 Answers1

2

To solve this problem, I had to break it down into two parts. First is the calling of Coroutines through a Static Method. Unity does not allow Coroutines to be called by default, but a class can be created to emulate this behaviour. The "StaticCoroutine" class 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:

using System.Collections;
using UnityEngine;

public class StaticCoroutine : MonoBehaviour {
    private static StaticCoroutine m_instance;

    // OnDestroy is called when the MonoBehaviour will be destroyed.
    // Coroutines are not stopped when a MonoBehaviour is disabled, but only when it is definitely destroyed.
    private void OnDestroy()
    { m_instance.StopAllCoroutines(); }

    // OnApplicationQuit is called on all game objects before the application is closed.
    // In the editor it is called when the user stops playmode.
    private void OnApplicationQuit()
    { m_instance.StopAllCoroutines(); }

    // Build will attempt to retrieve the class-wide instance, returning it when available.
    // If no instance exists, attempt to find another StaticCoroutine that exists.
    // If no StaticCoroutines are present, create a dedicated StaticCoroutine object.
    private static StaticCoroutine Build() {
        if (m_instance != null)
        { return m_instance; }

        m_instance = (StaticCoroutine)FindObjectOfType(typeof(StaticCoroutine));

        if (m_instance != null)
        { return m_instance; }

        GameObject instanceObject = new GameObject("StaticCoroutine");
        instanceObject.AddComponent<StaticCoroutine>();
        m_instance = instanceObject.GetComponent<StaticCoroutine>();

        if (m_instance != null)
        { return m_instance; }

        Debug.LogError("Build did not generate a replacement instance. Method Failed!");

        return null;
    }

    // Overloaded Static Coroutine Methods which use Unity's default Coroutines.
    // Polymorphism applied for best compatibility with the standard engine.
    public static void Start(string methodName)
    { Build().StartCoroutine(methodName); }
    public static void Start(string methodName, object value)
    { Build().StartCoroutine(methodName, value); }
    public static void Start(IEnumerator routine)
    { Build().StartCoroutine(routine); }
}

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.

The second part of the question is loading levels via Static Coroutines. Keep in mind that Application.LoadLevel is considered an Obsolete method, and was replaced with Unity's SceneManager. In this case, the simplest level change can be accomplished as follows:

SceneManager.LoadScene("SceneNameHere", LoadSceneMode.Single);

which will replace the currently loaded level with the new one. Indices won't work for this, so you'll need the scene name to make the transition. A preferred method is to use LoadSceneAsync() to avoid pauses or performance hiccups while loading. The Scripting Page for this method has an implementation which uses IEnumerator, which is completely compatible with both your code, as well as StaticCoroutine.