Saving during levels (whole scene state) and saving in between levels (relevant parameters only)

Hi,

i have a save system implemented that is basically this:

I just changed how and when Save and Load are loaded.
For now I can save in between levels, keeping track of things like player health, collectibles and of course the current level. And load up the last session from the main menu.

I would like to be able to save during a level. Think of my game as an “open world chicken invaders”. I have hundreds of enemy objects that are moving.
I would have to keep track of all of them, and I don’t know how to do it.

If this is not possible or very hard to do, then I would have to overthink my game design for later levels, as I can’t make them long, without forcing the player to play through them in one go.
It’s not that big of a deal, but I still like the freedom of being able to save whenever.

If you need more information about my game to give advice, feel free to ask.

How are you finding them right now? Do the same thing mid-level!!

Load/Save steps:

https://discussions.unity.com/t/799896/4

An excellent discussion of loading/saving in Unity3D by Xarbrough:

https://discussions.unity.com/t/870022/6

Loading/Saving ScriptableObjects by a proxy identifier such as name:

https://discussions.unity.com/t/892140/8

When loading, you can never re-create a MonoBehaviour or ScriptableObject instance directly from JSON. The reason is they are hybrid C# and native engine objects, and when the JSON package calls new to make one, it cannot make the native engine portion of the object.

Instead you must first create the MonoBehaviour using AddComponent() on a GameObject instance, or use ScriptableObject.CreateInstance() to make your SO, then use the appropriate JSON “populate object” call to fill in its public fields.

If you want to use PlayerPrefs to save your game, it’s always better to use a JSON-based wrapper such as this one I forked from a fellow named Brett M Johnson on github:

https://gist.github.com/kurtdekker/7db0500da01c3eb2a7ac8040198ce7f6

Do not use the binary formatter/serializer: it is insecure, it cannot be made secure, and it makes debugging very difficult, plus it actually will NOT prevent people from modifying your save data on their computers.

https://docs.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide

I have a spawn area around my player in an “infinite world” where objects are spawned and respawned.
Example:

I have 3-5 enemy types, each having some hundred of instances, that vary in size, speed and of course position. Possibly health etc.
I don’t know how I would save everything for each instance.

For my player thats not a problem, I just save the data from the player script and the number of my level. Then just load the level and all the players stats. So I have 70% health and I am in level 3, the game will simply load the scene with level 3 and give the player 70% health.
But I have no clue how to do that for multiple instances.

A bit more context how my game works:
I have a “Spawn object”, which will ramdomly spawn x objetcts of y in the beginning of each level. If those objects leave the spawn area, they will get respawn inside that area randomly again.
This means, no matter what I do, every time the scene is loading, that script will run and spawn x objects.
Even if I manage to save a whole scene, stuff like this is also in the way, I would have to somehow stop all the scripts from calling Start()
I’m sure this is possible somehow, but I am absolutely lost

The long and short is that you should be, or want to, keep track of these enemies as you spawn them.

A factory pattern would be useful here, with your spawners just asking an overarching system - lets call it EnemyManager - to spawn new instances, with the EnemyManager keeping track of everything that it has spawned. Then when it comes time to save, you already have references to everything, and can just write out their position, health, etc, ready for you to read from afterwards.

Then don’t have the spawners act on their own accord. Something else should tell them to start spawning, presumably only when a level is generated the first time.

Actually after the initial generation the spawners aren’t really needed. Your save system will know where everything else, and can tell the EnemyManager where to spawn everything.

Good advice for the future is to think about your goals with your save system ahead of time. Save Systems can’t be an afterthought, you need to build your systems with saving in mind. Otherwise you can hit situations where you have to roll back a whole lot of work because it’s not compatible with a save system.

Would it be

That is true and as a CS student who just took a software engineering class I shouldn’t have ignored that.
I started the game as a learning method, but later decided that I want to actually build my first full game.
Then I realized to late that I also need save system.
My project isn’t huge yet, so I might still be all to reroll my enemy objects.

Just to be clear tho, I have a spawn object, where I pass the prefabs in. The spawner instanciates the hundreds of enemies out of the corresponding prefab.

Wouldn’t it be too hard on the cpu tho to keep track of 100s of objects data?
What if I create a List with all the objects that are spawned, and once the players saves the game, the manager copies the info? On Load I would have to spawn each object not randomly, but from the loaded data? I would have to give the enemy spawner just am if-statement to let it know if the scene got loaded up from a savefile or not?

Is this too complicated? Or is that more or less what you mean?

I probably will just keep the saving system as is and have to keep in mind that I can’t design levels that take too long. Maybe sub divide a level into 2 scenes which can be saved individually,

Next time I will have to do that right from the start the right way.

You’re just keeping a reference to them, which is a small piece of memory. Them just existing in a scene is going to use substantially more resources than just holding onto a reference of everything that you’ve spawned.

Yes that’s pretty much inline with what I already said.

Though you only need to write out the information you care about, and not everything (as you can’t serialise out Unity objects in their entirety, despire what products like Easy Save might lead you to believe otherwise).

I will say my advice didn’t mean I thought your current arrangement wasn’t salvageable. If anything it should be relatively straight forward to implement what you want into your current project.

I was saying in future you should remember to keep requirements like these in mind because you can potentially end up in a situation where lots of work needs to be undone. But that doesn’t seem to be the case here.