You often want to run a coroutine, but you don’t want to run multiple copies of that coroutine.

One common use case is to have a button that visibly pops onto the screen and back out as it is enabled and disabled. You might write a coroutine that expands the transform of that button every frame in a very pleasing lerp effect, but find that if the user clicks back and forth very quickly then more than one coroutine can be started at the same time in a very unpleasing way.

RunCoroutineSingleton allows you to fix that. The normal way to use it is to apply a unique tag to every coroutine in the set (for this example that would be every coroutine that moves that button). You can then call Timing.RunCoroutineSingleton(_ButtonPopIn(button.tranform, “HealthButtonMovementSet”);

Tags do result in a memory alloc, so if you are trying to be as efficient as possible with your GC allocs then you might want to use a handle to define your singleton.

class Foo
  CoroutineHandle handle;

  void Start()
    handle = Timing.RunCoroutineSingleton(_MoveThatThing(), handle, SingletonBehavior.Overwrite);


The third parameter that you pass in is an enum that determines how any conflicts that are found will be handled. Abort will fail to run the current coroutine if one is already defined that matches your parameters. Overwrite will kill any matching coroutines and then run yours. Wait will automatically keep your coroutine paused until all the matches have finished and then it will execute.

One thing that you can do with the wait behavior is to set up a sequence of coroutines to run one after the other by giving them all the same tag and setting them to wait. Each coroutine will only wait for the coroutines that exist with that tag at the moment it’s created, later additions with the same tag will be ignored.

Below are some examples of usage:

Timing.RunCoroutineSingleton(_ButtonPopIn(button.transform), "HealthButtonMovementSet", SingletonBehavior.Overwrite);
Timing.RunCoroutineSingleton(_ButtonPopIn(button.transform), "HealthButtonMovementSet", SingletonBehavior.Wait);

CoroutineHandle handle; // This would normally be a private class variable.
handle = Timing.RunCoroutineSingleton(_ButtonPopIn(button.transform), handle);
handle = Timing.RunCoroutineSingleton(_ButtonPopIn(button.transform), Segment.FixedUpdate, handle);