Persistent room manager

Godot Version

4.5

Question

I want to make a room system with persistent rooms. I am aware of the difference between freeing scenes from memory, hiding them, and removing them from the node tree. The latter solution probably works the best for metroidvania-like room managers. I just want to ask what would be a preferred practice to make such.

So far I have tried to make two systems. A) keeping previous room in a single variable and forgetting everything else, and B) making a dictionary where scene file path works as a key and the saved PackedScene is the value itself. However, I’ve had some troubles loading different rooms correctly and made some duct tape solutions to fix that. (For example the manager skips a room and throws a player to another room. With a timer on enter_tree I was able to prevent this happening.)

Is there some bomb-proof elegant way of making a system that remembers multiple rooms? (Maybe they would get cleaned when entering another overworld or something.) Or should I stick with some single variable solution for the sake of performance and such? There’s probably not universally correct way to do this but are there any established conventions to approach this issue?

1 Like

I think the “best” way to store data between rooms is simply not to keep them in memory at all, but instead using an autoload singleton that will store all the data you need to save from that room. It really depends on your needs however. This will make it so that rooms have to be reloaded each time yes, although you can couple a few rooms together into one scene if they’re close enough.
For my game I created a ‘persistence component’ which will take any variables from the parent node I want, all of those are then stored into a dictionary, and then another dictionary that has the node paths and corresponding dictionary of variables gets fed into the save game manager singleton, then simply when the scene is reopened it looks for each object that was saved and feeds them the saved variables. Probably not the most elegant solution but it works for my needs, and it only saves the variables of objects that need it instead of the entire scene. But the way you do it depends on your needs heavily, if basically every object in the scene needs saving then other solutions might work better.

2 Likes

As you correctly guessed, there are no universally correct way to approach this problem, and it entirely depends on you current needs.

You listed multiple very valid methods. Some other methods I can think of from the top of my head:

  • Spatially spaced rooms: Instantiate all scenes at the same time, leaving space between them, and just move the camera/character to the correct room.
  • Stacked rooms, each inside its own SubViewportContainer. You can hide/silence inactive containers and only show the current room.
  • Load and instantiate the current room only. This is best if your rooms are too heavy to all exists on the tree at the same time, but might not be viable if you need the rooms to run a process even when not active.
  • Load and instantiate every room, but only keep the active room in the tree, keeping the others in a dictionary. (In this case, don’t forget to free the scenes in the location/overworld’s destructor method).

If you unload scenes entirely, it could be helpful to take a data driven approach, managing state entirely in a data class, and having the room scene simply reflect that data. This would make the room state persistent without having to keep the scenes themselves.

Again, there are sadly no perfect solution for this, just pick a method that produces a close enough result, and doesn’t make your development experience too inconvenient.

2 Likes

The obvious best way is to keep all room scenes in the memory and just swap them in and out of scene tree. You have zero serialization problems there. The obvious drawback is storage. But if your game types is such that the amount of data per room is not large in the context of your target hardware, then do precisely that. This, of course wouldn’t be sufficient if you need persistence between play sessions aka savegame. But others have already commented on that.

2 Likes

Thank you all for your perspectives. I think I’ll just keep polishing my own system and hope it works in the future as well. Storage might not be issue, at least with my small retro games, even though my sloppy optimisation might not work for retro hardware lol.