Last active
February 9, 2022 10:12
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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..."); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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());