I Built Coroutines for My Game Engine, Then Didn't Use Them
I built a generator coroutine system for my game engine. It had 122 lines of code and 12 tests. It solved the callback hell problem. It made scripts look like straight lines.
Then I chose not to use it for my game logic. I used a Finite State Machine (FSM) instead.
Here is why.
Most tutorials ignore two massive problems with generators in real-time games: memory and saving.
- Memory Pressure Every time you call .next() on a generator, the JavaScript engine creates a new object. This object contains the current value and the status.
In a game loop running at 60 FPS, this creates constant garbage collection pressure. My engine follows a zero-allocation rule to keep performance stable. Generators break that rule. They create a stream of small objects every single frame.
- The Serialization Problem A game needs to save and load. You need to turn the current game state into data and back again.
You cannot serialize a paused generator. Its state lives in internal engine slots that you cannot access. If you try to save it, you get an empty object or an error.
A Finite State Machine is different. The state is just a string on a component.
- To save: Write the string to disk.
- To load: Read the string and tell the FSM to start there.
The FSM won because it handles the two things that matter for a professional game: performance and persistence.
How to choose:
Is the logic inside the main frame loop?
- No: Use a generator coroutine. They are great for one-time flows like loading assets or onboarding.
- Yes: Ask the next question.
Does the state need to survive a save?
- Yes: Use a Finite State Machine.
- No: Ask the next question.
Are you running many sequences at once?
- Yes: Use a Finite State Machine.
- No: Use a generator coroutine.
Generators are not a mistake. They are just the wrong tool for the hot path. Use them for async glue, but use FSMs for your game logic.
Source: https://dev.to/grzott/i-built-generator-coroutines-for-my-game-engine-then-didnt-use-them-o3g
