- Home /
StopCoroutine not returning to yield
Hello,
I am currently building a small cutscene system for my game, based on Coroutines. The basic structure has a Cutscene
base class, with abstract void StartCutscene()
, IEnumerator RunCutscene()
and void EndCutscene()
methods, respectively for setting up, running, and tearing down the cutscene state as well as restore normal gameplay state.
The simplified code sample works like this:
public abstract class Cutscene : MonoBehaviour {
private Coroutine runHandle;
public void Run() {
StartCoroutine(CutsceneRoutine());
}
abstract protected void BeforeCutscene();
abstract protected IEnumerator RunCutscene();
abstract protected void AfterCutscene();
private IEnumerator CutsceneRoutine(IEnumerator run) {
// Finish current frame before running cutscene
yield return new WaitForEndOfFrame();
// Set up cutscene state
BeforeCutscene();
// Run the cutscene, keep a reference to the Coroutine,
// then wait until the cutscene is finished
this.runHandle = StartCoroutine(RunCutscene());
yield return this.runHandle;
this.runHandle = null;
// Tear down cutscene state,
// return to gameplay state
AfterCutscene();
}
}
Now I want to extend this system to allow skipping a cutscene. I added a component that keeps track of a button being held down, and finally calls void Skip()
on the currently running Cutscene instance.
My approach to skipping the cutscene was to simply use StopCoroutine
stopping the RunCutscene
and then continue with teardown and restoring normal gameplay state.
However, when the implementation looks like this:
public void Skip() {
if (this.runHandle != null) {
var handle = this.runHandle;
this.runHandle = null;
StartCoroutine(SkipRoutine(handle));
}
}
private IEnumerator SkipRoutine(Coroutine handle) {
yield return /* [...] fade out the screen */;
StopCoroutine(handle); // <-- (!) Important line here (!)
yield return /* [...] fade screen back in */;
}
This does not only kill the Coroutine
produced by StartCoroutine(RunCutscene())
, but also kills the CutsceneRoutine
currently in yield
on the other routine.
Is this a known or intended behaviour, am I doing something wrong, or is this a bug/unintentional behaviour in Unity itself? Is there any way to stop a coroutine from outside without killing the coroutine waiting on it as well?
Thank you and have a nice day, Alexander
Small update: I worked around the issue by running the teardown within the SkipRoutine
. It would still be interesting to know why StopCoroutine
kills the routine waiting in yield
as well.