You’re constructing a series of thing happening in time, perhaps unrelated to each other, and today you don’t really know 100% of what you will ultimately need.
Yes, a Queue() can certainly help, but that can only get you so far, such as “do one thing per frame.”
Well what if you want action 1 to take one second, and action 2 to be half a second, action 3 needs to wait for user input before proceeding, etc?
One way is to structure each step (the basic “thing” you put into a queue) as some sort of common object or interface that you can “pump” until it is done, then move onto the next “thing.”
This makes it very analogous to Coroutines, which are just things that get pumped until they’re done.
You can even pump coroutines yourself if you like, by calling MoveNext() on the returned IEnumerator object to execute each step, and when it is done, go onto the next one.
If you need a composite you can make one of those too: eg, a step that requires action 1A to be done at the same time as action 1B, but you don’t want anything to move forward until BOTH are guaranteed done. In that case you make a Coroutine that accepts and runs the other two, not saying it is done until both are done.
Our very own Bunny83 has also provided a Coroutine Crash Course:
And here’s some more readings:
Coroutines in a nutshell:
Splitting up larger tasks in coroutines:
Coroutines are NOT always an appropriate solution: know when to use them!
“Why not simply stop having so many coroutines ffs.” - orionsyndrome on Unity3D forums