Things to check before starting a coroutine?

Calling coroutine outside of the gameobject sometimes yields ERROR. I met two yet: 1) the monobehaviour is being destroyed; 2) the gameobject is inactive. So what else should I care about before I start a coroutine?

public void StartFindPath(Vector3Int startCoords, Vector3Int endCoords)
    {
        if (this && gameObject.activeInHierarchy) // checking if I can legally start a coroutine
        {
            findingPath = true;
            StartCoroutine(FindPath(startCoords, endCoords));
        }
        else
        {
            onPathfindingFinished?.Invoke(this);
            PathfindingManager.FinishProcessingPath(null);
            findingPath = false;
        }
    }

That seems pretty good to me. The other thing you might be concerned with is if the coroutine is already running. If it’s possible for the coroutine to be started/restarted more than once, you might want to make sure you only have it running once. You can avoid that by calling StopCoroutine() before starting the coroutine again. For example:

private Coroutine _countdownCoroutine;
public void BeginCountdown(float time)
{
    if (_countdownCoroutine != null)
    {
        StopCoroutine(_countdownCoroutine);
        _countdownCoroutine = null;
    }
    _countdownCoroutine = StartCoroutine(Countdown(time));
}

There may be cases where having one coroutine running multiple times on the same object is fine, but usually I find I want to interrupt the current routine and start over fresh with the new one.

The real question what you want to do otherwise? At the moment you essentially circumvent the issue by not calling StartCoroutine. Though the question is why do you actually call this method in the first place? So there has to be a conceptional issue in your setup when this actually happens. In some rare cases just ignoring such issues may be a solution, especially when you need a quick fix late in development.

However in a proper designed application this should never happen in the first place and ignoring / swallowing such issues blindly could actually hide other deeper issues. Don’t be afraid of errors, they are here to help you.

Though that said we don’t have the full picture of your design, so this may be the right place to check for the state of the object.

The main thing to check before calling / making a coroutine is to ask yourself,

“Does this even need to be a coroutine?”

Generally, if your design requires you to call StopCoroutine(), then don’t make it a coroutine.

If you just need something to happen a bit later, this is a more-robust approach:

https://gist.github.com/kurtdekker/0da9a9721c15bd3af1d2ced0a367e24e

If you’re flipping from one value to another, such as fading in, fading out, changing speeds slowly, etc., coroutines are an AWFUL solution to that. Instead use a pattern like this:

Smoothing movement between any two particular values:

https://discussions.unity.com/t/812925/5

You have currentQuantity and desiredQuantity.

  • only set desiredQuantity
  • the code always moves currentQuantity towards desiredQuantity
  • read currentQuantity for the smoothed value

Works for floats, Vectors, Colors, Quaternions, anything continuous or lerp-able.

The code: https://gist.github.com/kurtdekker/fb3c33ec6911a1d9bfcb23e9f62adac4

If you just need cooldown timers for limiting gunfire rates, use a cooldown timer:

Cooldown timers, gun bullet intervals, shot spacing, rate of fire:

https://discussions.unity.com/t/821482/2

GunHeat (gunheat) spawning shooting rate of fire:

https://discussions.unity.com/t/824570/2

Far too often people (including very popular tutorial sites on Youtube) reach for needless coroutines and make a colossal unstable mess of their codebases as a result.

Also: https://discussions.unity.com/t/849607/7

3 Likes
How do I create a repeating Delay?
Coroutines
How to make a coroutine loop correctly?
Nested loops in coroutine
List doesn't want add more than one instantiated prefab?
Coroutine does not work properly
Coroutine Not Stopping
[SOLVED] Coroutine not working properly
Sound Trigger Issue in Unity
How to wait between instructions, for keypress for example, inside a method
Coroutine not starting
The code is not executing the expected thing.
I'm trying to move an object without Update().... Not successing so far.
Lerping the Main Camera not working?
I can't stop my coroutine.
I don't get coroutines.
Can't play the audio source via script
Where would I put WaitForSeconds and the Coroutine for this to work?
Attack 2 enabled collider appears before Attack 1 disabled collider Causes Attack 2 collider Enable to be missing
Why Do Functions With Yield Not Execute (Sometimes)?
Function is called but nothing happens?
Delay in program?
Coroutine for heavy operation
Benefits of implementing a state machine similar to QuizU?
is it proper to call coroutine as a normal method?
IEnumerator
What is the proper way to delay AI actions in a pokemon clone, so it isn't instant
StopCoroutine() not stopping my Coroutine?! [RESOLVED]
Unity Vector2.MoveTowards() is teleporting instead of moving dynamically
Coroutine error
Problem Calling Animation
Coroutines memory allocation on every yield (bug?)
How can i stop a Coroutine while its playing
How to Use System.Timers.Timer With unity GameObjects
Function not waiting
When I start a coroutine by clicking on a button, does everytime i click it again, starts a new one?
A while(true) loop with a for() iterator inside a Coroutine ?
Timer via Coroutine
How to wait with For Loops?
Coroutines with while loop instead of update with if statement
Enter and Exit pointer Called everySecond at UI Element
How to extend coroutine triggered by event
How to loop a repetitive movement during a specific time frame
I need help with my 2D movement
Best approach to turn based base games - Avoid triggering all code same frame
StopCoroutine(), when does it stop?
Coroutine stored in a variable class seperated from the Mono Behavior
I'm addicted to using Coroutines. Any alternatives?
StackOverflowException when trying starting a coroutine
Is a singleton the best design solution for a property manager?
I can't get StopCoroutine to work?
Custom timers working with EditorApplication.update but not working with Update at runtime
Coroutine never truly stops?
Game ceases to function
Difference Between WaitForSeconds(Time.deltaTime), yield return null, and WaitForEndOfFrame() in Unity
Why can't I just animate one axis of localPosition?
help with movement code

The design is that pathfinding is performance heavy and I’m splitting the work across frames by using yield return null. If a unit needs a path then it informs PathfindingManager and the manager queue up those requests and executes them one after another. The problem comes when a unit requests a path but die/inactive by the time the manager executes its FindPath. In that case the manager should move on to the next request.

That sounds like a very legitimate coroutine use.

The method I would do is to have a single pathfinding manager that the units ask for pathfinding, then they get a callback when the pathing is done.

That way if they have died, the pathing callback just dumps data into a dead object for subsequent consumption during that dead object’s Update() loop… which never happens!

The you can put in an OnDisable() method in each destroy-able object that can call the pathfinding manager and say “hey if you had business for me, forget it, I’m outie…”

Or it could just let the work be done and discard it.

The above lets everybody NOT care about what anybody else is doing. Everybody just knows what to do.

1 Like