Skip to content

Instantly share code, notes, and snippets.

@sttz
Last active February 9, 2022 10:12
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sttz/4578868 to your computer and use it in GitHub Desktop.
Save sttz/4578868 to your computer and use it in GitHub Desktop.
Simple wrapper around Unity coroutines (generator methods) that allows to stop them from the outside. Unity natively only allows this when starting the coroutine by using its lexical name.
using System;
using System.Collections;
using UnityEngine;
/// <summary>
/// Wrapper around coroutines that allows to start them without using
/// their lexical name while still being able to stop them.
/// </summary>
public class StoppableCoroutine : IEnumerator
{
// Wrapped generator method
protected IEnumerator generator;
public StoppableCoroutine(IEnumerator generator)
{
this.generator = generator;
}
// Stop the coroutine form being called again
public void Stop()
{
generator = null;
}
// IEnumerator.MoveNext
public bool MoveNext()
{
if (generator != null) {
return generator.MoveNext();
} else {
return false;
}
}
// IEnumerator.Reset
public void Reset()
{
if (generator != null) {
generator.Reset();
}
}
// IEnumerator.Current
public object Current {
get {
if (generator != null) {
return generator.Current;
} else {
throw new InvalidOperationException();
}
}
}
}
/// <summary>
/// Syntactic sugar to create stoppable coroutines.
/// </summary>
public static class StoppableCoroutineExtensions
{
public static StoppableCoroutine MakeStoppable(this IEnumerator generator)
{
return new StoppableCoroutine(generator);
}
}
/// <summary>
/// Example of using the StoppableCoroutine wrapper.
/// </summary>
public class Example : MonoBehaviour
{
// MonoBehaviour.Start
protected IEnumerator Start()
{
// Create the stoppable coroutine and store it
var routine = MyCoroutine().MakeStoppable();
// Pass the wrapper to StartCoroutine
StartCoroutine(routine);
// Do stuff...
yield return new WaitForSeconds(5);
// Abort the coroutine by calling Stop() on the wrapper
routine.Stop();
}
// Coroutine that runs indefinitely and can only
// be stopped from the outside
protected IEnumerator MyCoroutine()
{
while (true) {
yield return new WaitForSeconds(1f);
Debug.Log("running...");
}
}
}
@lefth
Copy link

lefth commented Feb 15, 2018

This gist was modified a year ago, but even at that time, this technique was not necessary. Coroutines can now be stopped with StopCoroutine(coroutine), assuming you kept the return value as: var coroutine = StartCoroutine(generator());

@Den999
Copy link

Den999 commented Jul 23, 2021

+++

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment