http://answers.unity3d.com/questions/1182632/problem-with-stopping-nested-coroutines-control-ne.html
Errors using StopCoroutine with nested coroutines
I am having trouble stopping nested coroutines using StopCoroutine. I included minimal code for a component (CoroutineTest) that reproduces the issue at the bottom of the question.
If I Play a scene in Unity with a CoroutineTest component attached and active to a game object, and then Stop the game a second later, I get the following errors while the game is trying to quit:
coroutine->m_WaitingFor->m_ContinueWhenFinished == coroutine
coroutine->m_RefCount > 0
coroutine->m_CoroutineEnumeratorGCHandle != 0
All with the same callstack:
UnityEngine.MonoBehaviour:StopCoroutine(Coroutine)
CoroutineTest:OnDisable() (at Assets/CoroutineTest.cs:15)
The errors are a little vague but it looks like they some kind of garbage collection failure with my coroutines. I'm not sure what I'm doing wrong.
I noticed two things:
I get no errors if I use StopAllCoroutines instead of StopCoroutine(outerRoutine)
I get no errors if I no longer nest a call to StartCoroutine(InnerRoutine())
I would like to keep some coroutines running when the component is disabled, while stopping others, so StopAllCoroutines is not suitable for me. Is there a way I can use StopCoroutine without causing errors when the game stops?
Here is the code for the component:
using System.Collections;
using UnityEngine;
public class CoroutineTest : MonoBehaviour
{
private Coroutine outerRoutine;
public void OnEnable()
{
outerRoutine = StartCoroutine(OuterRoutine());
}
public void OnDisable()
{
StopCoroutine(outerRoutine);
}
private IEnumerator OuterRoutine()
{
yield return StartCoroutine(InnerRoutine());
}
private IEnumerator InnerRoutine()
{
yield return new WaitForSeconds(4f);
}
}
I just noticed that if I start and stop coroutines using strings ins$$anonymous$$d of IEnumerators (ex. StartCoroutine("OuterRoutine")), the code works without errors. So what's the difference with using Coroutine types as arguments?
I may have found my mistake! Re-reading the documentation for StopCoroutine I see that the signature is:
public function StopCoroutine(routine: IEnumerator): void;
but I'm passing in a Coroutine ins$$anonymous$$d of an IEnumerator! This didn't cause any compile errors but I think it's a misuse of StopCoroutine nonetheless. The following code fixes the issue and I will do this from now on:
IEnumerator outerRoutine;
public void OnEnable()
{
outerRoutine = OuterRoutine();
StartCoroutine(outerRoutine);
}
public void OnDisable()
{
StopCoroutine(outerRoutine);
}