Orchestrating the “play out” of a series of game events generally involves either:
tracking a timer yourself and acting each step out, or
using a coroutine to pause between the different phases of doing things.
I like the coroutine approach and a common coroutine runner that accepts other coroutines and runs them one after the other, waiting for each one to complete before moving on.
Coroutines in a nutshell:
Hey Epoch, here’s how it goes down. A coroutine is just an IEnumerator object, and you make one by just calling a coroutine.
When you do that, nothing happens. It’s like a water pump that needs to have its crank pumped, but nobody is pumping it so it sits there and does nothing.
In Unity there’s a special agreement: if you hand that IEnumerator object into StartCoroutine(), which is a method belonging to the object where that StartCoroutine() call is located, what Unity does is starts “pumpin…
Coroutines are an IEnumerator object. They have their own internal state. It’s different from just calling InvokeRepeating(), which would restart a fresh function call each time.
Here is ALL you need to know about coroutines in Unity:
they are an IEnumerator, also known in some languages as a Generator. It is an object with a .MoveNext() method on it that “yields” the next thing with each subsequent call. That is what you create by calling an IEnumerator: you create the object, you do NOTHIN…
Splitting up larger tasks in coroutines:
Technically, yeah, there’s always a way. But in practice, in the general sense it can get really hairy.
Also, in the particular case of adding lots of GameObjects, I know they’re not linear: last I checked, adding 1000 GameObjects is WAY more than 10x slower than adding 100 Gameobjects, I presume due to inefficiencies in newly-added stuff, not sure/ No way to tell with a closed-source engine like Unity.
Trying to tie into system timers and judge how long things have taken so far will get you …
Coroutines are NOT always an appropriate solution: know when to use them!
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 AW…
There’s never a need. As @PraetorBlue pointed out in a recent post of his, nobody NEEDS coroutines.
They do solve a certain class of problem nicely however, primarily problems of sequencing a set of data or events to happen.
Coroutines CAN be interrupted and restarted but doing so exponentially increases your chance of a bug, negating a lot of their inherent benefits.
A lot of human behaviors are good coroutines: “Go take a shower.”
So that breaks down to:
get undressed
start the shower
…
Our very own Bunny83 has also provided a Coroutine Crash Course:
https://answers.unity.com/questions/1749615/coroutines-ienumerator-not-working-as-expected.html?childToView=1749714#answer-1749714