I’ve been writing lots of coroutines lately. A common functionality is that I need stop an existing coroutine before starting it (if it’s already running). Another common functionality is that I need to be able to see if a given coroutine is running. Typically this is how I accomplish this:
For a class that has a few different coroutines this starts to get a little ugly. Is there a better way to do this? I guess I write a custom class for this.
What I like to do is have a manager that handles the actual coroutines. It allows you to actually start, stop, and keep track of things that are running… for example:
public class CoroutineManager : MonoBehaviour
{
private static CoroutineManager Instance
{
get
{
if (mInstance == null)
{
mInstance = new GameObject("CoroutineManager").AddComponent<CoroutineManager>();
GameObject.DontDestroyOnLoad(mInstance.gameObject);
}
return mInstance;
}
}
private static CoroutineManager mInstance;
private static Dictionary<string, Coroutine> runningRoutines = new Dictionary<string, Coroutine>();
private static IEnumerator InternalRoutine(string key, IEnumerator routine)
{
yield return routine;
runningRoutines.Remove(key);
}
public static void Start(string key, IEnumerator routine)
{
Stop(key);
var internalRoutine = Instance.StartCoroutine(InternalRoutine(key, routine));
runningRoutines.Add(key, internalRoutine);
}
public static bool IsRunning(string key)
{
return runningRoutines.ContainsKey(key);
}
public static bool Stop(string key)
{
Coroutine routine;
if (runningRoutines.TryGetValue(key, out routine))
{
Instance.StopCoroutine(routine);
runningRoutines.Remove(key);
return true;
}
return false;
}
}
Then you can use it like this
public class ExampleScript : MonoBehaviour
{
private const string KEY = "TEST";
private void Start()
{
CoroutineManager.Start(KEY, TestRoutine());
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
if (!CoroutineManager.IsRunning(KEY))
{
Debug.LogFormat("Routine {0} is not running... Starting it", KEY);
CoroutineManager.Start(KEY, TestRoutine());
}
}
if (Input.GetKeyDown(KeyCode.Escape))
{
if (CoroutineManager.Stop(KEY))
{
Debug.LogFormat("Stopped Routine {0}", KEY);
}
}
}
private IEnumerator TestRoutine()
{
Debug.Log("Hello");
yield return new WaitForSeconds(5);
Debug.Log("World");
}
}