Coroutines: Stopping a Coroutine from Within Itself

I am driving my camera using coroutines. At the moment, there are three:

FadeToColor();
MoveToLocation();
FollowTarget();

I’m trying to manage the coroutines in an intuitive way so that multiple coroutines aren’t running when they would conflict.

Some examples:

  1. If MoveToLocation is running and another MoveToLocation is started, the first should be stopped.
  2. If FollowTarget is started, any MoveToLocation or FollowTarget currently running should be stopped.
  3. In both cases, FadeToColor should be allowed to continue.
  4. If FadeToColor is running already, and a new one is started, the previous one should be stopped.

I am using this really handy Task manager interface to handle coroutine start/stop/pause from external methods where necessary. It’s proving to be super helpful. But what I’m hoping for is similar functionality within the coroutine itself, where the coroutine has knowledge of it’s own running ‘instance’.

Ideally, I’d be able to arbitrarily call MoveToLocation(Vector3 loc) at any time and have any currently running MoveToLocation() identify that a new one has been started and cancel itself.

Any advice?

I solved this myself (surprised…) and thought I’d share incase anyone else wants to achieve the same result. The solution was the put a wrapper Coroutine around the actual method, and use Ken Rockot’s Task manager above to handle the stop/starting of coroutines.

This allows using StartCoroutine to override any existing FadeToColor coroutine, or using ‘yield return’ to sequence FadeToColor coroutines as usual.

private Task t_fadeToColor;
public IEnumerator FadeToColor(Color newScreenOverlayColor, float fadeDuration)
{
	if (t_fadeToColor != null)
		t_fadeToColor.Stop();

	t_fadeToColor = new Task(FadeToColor_Coroutine(newScreenOverlayColor, fadeDuration));
	t_fadeToColor.Finished += delegate(bool manual) { t_fadeToColor = null; };
				
	while (t_fadeToColor != null) { yield return true; }
		
	yield return 0;
}

public IEnumerator FadeToColor_Coroutine(Color newScreenOverlayColor, float fadeDuration)
{
	while (fadeDuration > 0.0f)
	{
		fadeDuration -= Time.deltaTime;
		// FADE TO COLOR CODE HERE
		yield return true;
	}
			
	yield return 0;
}

There’s a one-frame (I think?) delay between the new coroutine starting and the old one finishing, which for my purposes is acceptable.

1 Like

Sorry to bump up the dead sheep, but I had to thank you for this post. It worked like a charm. I was busting my arse over this for quite a while. Cheers! :slight_smile: