How to stop ALL coroutines in a scene?

Of course I know “StopAllCoroutines” function,while it just works in a certain MonoBehaviour
How can I stop all coroutines on All MonoBehaviour running in this scene?Just like a new function “StopAllCoroutiesInThisScene” ):
Thank you very much!

Doesn’t exist. But you can write this function easily enough: just run FindObjectsOfType() and call StopAllCoroutines() on all of them.

Now why on earth would you want to do this? That part’s got me stumped.

1 Like

You could use a coroutine helper/manager that will hold all your coroutines.

1 Like

It sounds like bad idea to stop all coroutines in the project. Can you tell us for what you need it. Maybe you thinking in the wrong direction and we can show you another way to solve your problem.

1 Like

Hi. In my case, I am playing an “opening animation” in which a bunch of coroutines are running in different game objects. I hope that when the mouse is clicked, the game freezes the opening animation and fade out to the main menu.

One solution is that I use a single class to access all other objects and start coroutines in that class, then I can use “StopAllCoroutines”. But what if I insist different game objects running their own coroutines?

Thanks.

You could do it the other way around. Write some Monobehaviour which stops its own (and siblings) coroutines if an event X is received (like the mouse is clicked). Could be a component (StopCoroutinesOnMouseClick). That would spare you the trouble of maintaining a list or making a global manager. Also keeps things modular.

If you are really into it then ditch the coroutines, make it all async and use a CancellationToken to end them all. That’s what your own solution will approximate anyhow. Though I guess that might be a little too much for this problem.

I have a scene that must end suddenly and I am getting an error unloading the scene because it has coroutines running. I see no choice but to stop the coroutines before unloading the scene. Am I missing something?

When a game object is destroyed, all coroutines on it are stopped automatically. Unloading a scene causes all game objects in that scene to be destroyed, so all coroutines in the scene will thus automatically get stopped as well.

What was the error exactly and where was it coming from? Could it be that you were attempting to start a coroutine on a component in the scene that was already being unloaded? Or perhaps a coroutine was running on a component in another scene, and it was just referencing objects in the unloaded scene?

2 Likes

What’s the exact error message and related code?

2 Likes

Unloading the scene will stop all coroutines in it. Your error is likely unrelated to running coroutines. Maybe share the error and related code.

Another use case: I have a unique scene and many objects with monobehaviors that run coroutines at various moments in the game (for running animations for instance).
When the player hits the “new game” button, I have to reset everything, including stopping all coroutines.

What would be the cleanest and safest way to do this? By safe I mean that I’d like to be sure to stop all coroutines.

Options I see based on your comments:

  • Run FindObjectsOfType() and call StopAllCoroutines() on all of them.
    Super safe but not very clean? Could it be an issue if there are too many objects to scan for?

  • Implement a reaction to the event (press new game button) on each monobehavior to make it call StopAllCoroutines on its own.
    Clean, but one should be carreful not to forget any coroutine.

  • Simply reload the scene?

Any thoughts?

Have you tried just reloading the scene (as you suggested yourself)? If you can live with a little loading screen or hickup it might the best solution since resetting is hard (especially if physics are involved).

Otherwise you have already listed the most common solutions. Though I would not recommend using FindObjectsOfType. It’s slow and you may get more than you wanted or less than you wanted (in multi scene setups).

My recommendation there would be to turn the tables: Have some “Registry” object to which your MonoBehaviours register (possibly in Awake or OnEnable). That registry is nothing more than a list of all registered objects.

Then if the player ends the game simply iterate through all the registered objects in the registry and do whatever you need with them (reset, stop delete, dump old prefabs and reinstantiate). - I would recommend this pattern over Find… in almost all use cases.

2 Likes

I did not even think about physics, good point for reloading the scene then, thanks!

Maintaining a registry - as you mention - is currently what I am doing. My concern is that it relies on manually resetting everything (coroutines, parameters, physics), so Im happy having a more robust solution.

Then I think it’s either scene reload or (if the scene is too big) prefab re-instantiation (dump the old ones a spawn new ones in place of the old). Which is preferable depends on the size of your scene.

Personally, I like to do the prefab approach with player characters, NPCs or anything that has physics or complex internal logic. It saves your from reloading the whole level but still allowes for a relatively clean reset state of your dynamic objects.

make a monobehavior, find objects that doing its rutines of type go to sleep if mouse click ,set a time abd play fade in meantime then resume “I hope that when the mouse is clicked, the game freezes the opening animation and fade out to the main menu.” this way you dont remove a routine you just pause it