Saving State of Random Level Generation between Multiple Levels

I understand basic random level generation but how do you save the state of the level when a player leaves it and comes back to it so it is the same as when they last visited it?

Do I save every object and their position, rotation, game values like (NPC’s Health, NPC’s inventory, etc…) all in a singleton game manager? What happens if I have 100s if not 1000s of levels like this?

Example:
Player enters Scene 1 and it is randomly generated, buys 10 apples and kills a Boss.
They leave for Scene 2 which is randomly generated but quickly goes back to Scene 1.
How do I keep Scene 1 from being randomly generated (again) but the same as when they last visited and Scene 1 having 10 less apples and a dead Boss?

Thank you.

There are different approaches you can choose. Due to the need for many levels, I’ll disregard the easiest option, which is “just don’t unload the level objects”. You’d eventually run out of memory that way.

So step 1 is generating the same level again. This can be done by setting Random.seed to some value (often something time-related, like the number of milliseconds), and then saving that value. As long as your random generation algorithm is unchanged, that will generate the level the same way it did the first time. (Note that the Random class might change from platform to platform, so if porting these levels from one platform to another is going to be important, you’ll want to implement your own pseudorandom number generator that you have complete control over, which is not as scary as it sounds.)

While you’re spawning objects for the level, you can add them to appropriate Lists. Each time an NPC is generated, add it to a list. But, not the NPC GameObject itself, but rather, a new class you create with the [System.Serializable] attribute. This class should contain every piece of information about the NPC that will persist when the level is reloaded (Health, inventory, etc), as well as a (nonserialized) reference.

When you exit the level, this class will read in every fact about the NPC from the real object, and then you’ll serialize your Lists to a save file. (If you want to not have any limits to the number of levels whose state you can save, you’re gonna need to keep them in files, or you’ll eventually run out of memory.) The Random seed used for this level should also be serialized along with these Lists.

When you reload the level, first fully randomly generate it, but using the same seed as before. When you do, this will create a List of NPCs that should perfectly match the Lists you have in your save file, and then you can just apply that data to the objects you generated.

Thank you so much for your help. This was a big help.

If you also want to save NPC’s positions and collectibles, without them reapearing after you’ve killed them or collect them, one fast and easy solution, could be just to use a Scriptable Object.
Once the player is leaving the level you save all the info you need int the SO. You can for example have in the scriptable object a list of levels, and for each level you save the list of NPCs alive and the list of collectibles that are still there. You can make a serializableCollectible class, and a Serializable npc class with all the variables you want to save, and you can save in them not only the npcs position and type, but also their health or whathver you want. The scriptable object will persist any data you put into it. What I’m not really sure if it’s something that could be tempered easily by cheaters, but as a solution, is probably the most intuitive and fast I know of.

Interesting. I have not looked too much into Scriptable Objects. I thought they were just a way to create like items for game creation and not for runtime.