-
I'm playing with ECS and entt to see if it would make sense to migrate my existing (adventure-focused) engine to make certain parts a bit cleaner. I've only known ECS and entt for like 5 days, and I'm still in a prototyping phase to get a feel for it. I have an architectural question. My engine structures the game in several scenes (sometimes called rooms in the adventure genre). Each scene is fully independent from the others, and once the player goes from scene A to scene B, scene A should stop updating and rendering, and scene B should take over (might need to update and render both during crossover transitions). The state of the scenes is persistent. If the player goes back to room A, it should be again in the state it was left before. Besides scenes, I also have some global state, most importantly the inventory. Naturally, the contents of the inventory shouldn't change when changing scenes. Some scenes don't even render the inventory, but the contents must persist across scene changes. I have other "entities" that also persist their state across scenes, but the inventory is the most obvious. Also, not super important, but since I have multiple player characters, I also have multiple inventories to track independently. Games with separate scenes and persistent state across them are super common, so I thought about asking here. I did some homework, and here are some ideas I have so far:
This was my first intuition, but I don't like that systems need to get passed two registries to do their work. Any time a system needs information from both registries (e.g. the sprite renderer), the code gets more complex.
Systems would need to be passed the registry and also the current scene, so they can filter entities. The problem with this approach is that I would still have to iterate through entities across all scenes (on every system!), just to realize that most of them aren't in the active scene and must be skipped. That's a lot of wasted work that makes me very uncomfortable and would impose restrictions in how I structure my entities (for example, I couldn't unpack particle systems to create one entity per particle if I end up iterating all particle systems in all scenes). The globals at least live in the same registry, and I could just turn inventories on and off when changing scenes.
The idea in this case is that whenever the player is in scene A, entities belonging to that scene would have the
This idea is a bit more radical. I would destroy all entities from scene A and create the entities of scene B. To avoid losing the state of A, I would fetch the important bits (those that would go into a savegame) and set them aside for later. Global objects would never be destroyed (a special tag component can do that). It's the most memory efficient option, because my savegames don't hold onto support data like textures, or entt's sparse sets. But I don't like the idea of storing state in two places. My favorite option is 4, as it seems more idiomatic with my limited understanding of ECS. How do others deal with this situation? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
I prefer option 1 in a stack-like model where requests are propagated. For example, the update tick starts from the top and goes down to the base unless someone filters/stops it. Same thing for the rendering request, where the layer in the stack knows whether it's the top one or not (ie to shrink the amount of stuff to render).
Systems don't have to be aware of the fact that more than one registry exist actually. You can provide them with the current scene and make them ask the latter for the data of interest (ie current registry and global one, who cares if they're the same or not). Also, the rendering system doesn't have to access multiple registries in this case. Quite the opposite. You can invoke the draw function on the top scene, it does its stuff and propagates to the other scenes in the stack. Each scene can invoke the rendering system with its registry then. I don't see why it should know about all registries. |
Beta Was this translation helpful? Give feedback.
I prefer option 1 in a stack-like model where requests are propagated. For example, the update tick starts from the top and goes down to the base unless someone filters/stops it. Same thing for the rendering request, where the layer in the stack knows whether it's the top one or not (ie to shrink the amount of stuff to render).
Systems don't have to be aware of the fact that more than one registry exist actually. You can provide them with the current scene and make them ask the latter for the data of interest (ie current registry and global one, who cares if they're the same or not). Also, the rendering system doesn't have to acce…