Best practice to store cross-level state

Hey all,

I’m developing a single player game with many levels. The player transitions between those levels frequently, and both the levels and the players need to preserve state. E.g., door actors need to remember whether they’re open or closed, and the player needs to keep their inventory and stats.

How and where should this state be stored?

  • Character/Pawn, Player State, and Game State are all out of the question because they are recreated when the level changes.
  • Game Instance seems to be the only option with a sufficiently long lifecycle.

My current solution does in fact use the Game Instance, but this feels extremely wrong. I have made some wrapper classes around primitives (such as bool) that mirror their value to a TMap in the Game Instance. A DoorActor would have a variable of that type (BoolWrapper), and “SetValue” and “GetValue” would actually read from and write to a TMap which actually resides inside the Game Instance.

While this does work, it seems to violate every principle of software development, such as separation of concerns. Almost all objects need to externalize their variables to one god object. Mirroring the data only on Begin and End Play doesn’t change this substantially. And turning it around – having the Game Instance scrape the object tree and persist relevant data – requires even more knowledge in the Game Instance about things it should know nothing about.

Also, the Game Instance’s lifecycle has the opposite problem now: It’s no longer too short, but it’s now too long: You can’t even create a new one when the player clicks on “New Game”, and rather have to clear and reuse the old one.

I clearly must be missing something. How is this usually done?

use an actual save game object ha, you can save each level by their level name, append it onto the current save slot or autosave

Thanks for the repsponse. I fail to see how a Save Game helps though.

First, I’d then be abusing a Save Game object as a data container although I have no intention of using it for its primary purpose: saving.

Second, how does this solve any of the problems regarding separation of concerns and lifecycle? I’d still have to choose one of two evils: Either the save game needs to know how to collect all the data, or every object needs to know how and when to use the save game.

As said, I do have a solution that works, it just seems this will not scale for any slightly more comlex game and will result in code changes in many places should changes be required in the future. I feel the best way to address this would be through annotations or an aspect oriented approach, but I don’t think anything like this is available in UE.

Cheers

well the point of the save game is rather than remember all data all the time you can load it by level.

the way i do it is i have a save interface, when i want to save a level i getallactors with interface. each actor saves itself, it does this because each actor knows what it needs to save/load.

the save data itself can be generic, an array of transforms, an array of bools etc or structs for anything specific.

so for your example you have a door, the door needs to save is it open or closed. so you can save it in a generic array of bools as index 0. the door knows its index 0 so when it loads it grabs index 0 and set the isdooropen bool.

you can use the actor class as a reference or a ‘name’ id to confirm the data is of the correct type