Robust Save/Load System

I need advice on how to implement a robust save/load system. I’m not talking about simply saving a few variables. I’m talking about saving the state of a complex world simulation. A good example would be a hardcore RTS like StarCraft or Age of the Empires.

I need to be able to save the exact state of all the units in my game, including their active animations, position within AI trees, active pathfinding, active coroutines, fired projectiles, particle systems – pretty much everything. The player needs to be able to save and restore the game exactly as it was. Small discrepancies will break the simulation and produce unreliable results and open the door for cheating.

Doing a bit of research into this, it seems like rolling out a system that tracks individual variables is impossibly complex and error-prone. How would one go about taking a snapshot of the entire game state. I know there’s now built-in snapshot function, but what’s the best way to construct one? Or perhaps some plugin solution exists I don’t know about. I looked at EZ Game Saver, but it doesn’t seem like it would work well for a simulation game.

Seriously? I’m the first one that bumped heads with this problem? How do you guys create save/load systems?

I have used ascii files to save the state of lots of variables (maybe 50 or so) and then read them back in when the game is started again.

Reading your description, I imagine solutions in which things such as pathfinding are designed so that you do not have to save the actual state of pathfinding computations (or the state of coroutines as you added) but instead that the system is designed so that if you save the position of an object and its goal and that it is to be in a state of pathfinding (potentially only two variables there), then the pathfinding system would start again and resolve the path from that point with the same results as if the object had started from its point at some time earlier before the save point. This would be one example of the logic behind how most everything else would be handled.

It does make me curious however, what kind of application you are considering where you would want a player to be able to fire a projectile, then hit save and quit the game, and then start the game again and watch the projectile continue its path. If the projectile is a lunar mission to mars, then I can see why I would want my work saved, but if it is a grenade launcher I am not so sure. And also what the need for saving the state of a particle system - you mean the position of every particle?

It is an interesting idea to capture the state of everything - as if you are running the profiler in deep mode, capture everything like a memory stamp, and then reload it - but the useful application of it is what I still try to imagine - beyond what seems most likely as a means to cheat rather than not be able to cheat.

It also makes me think of neat ideas about save state for a game that “continues” after you exit and until you restart - e.g., you plant a tree and don’t play the game for a week but when you come back it has sprouted and growing. The game would not have processed during the off time, but when relaunched it looks at how much time has passed and does all the calculations to see where things should now be, and presents them that way at the new start point.

Sorry if none of that was helpful but it leads to interesting ideas. The short answer is that I think the first paragraph of my reply would be reasonable way to achieve it through scripting in Unity.

I just thought to add a note about an experiment I did on a recent network game project with an authoritative server setup.

When the client player exited the game, I set the server to a Time.timeScale of zero. This paused the server and the state of everything.
When the client player logs back in, it started back up right where it left off.

It was kind of cool, but I did not keep it that way, instead restarting the level when a client connects when previous connections were zero.

AFAIK

Step 1 - Build a simple and robust save system.

Step 2 - Integrate every single script into the system.

I’ve done step one, step two is a matter of really thinking every single script through, and lots of testing.

Yeah, that seems like the way to go. Thanks.

It’s not hard to imagine simulation games where saving the state of a projectile is critical to the gameplay. Most AAA games out there does this. I’m making a stealth game that will require the player to reload on death/failure, which will happen quite often.

Step 2 seems like nightmare for my game. I have to redesign all the code, and the code is pretty complex. I’m not sure how I will handle cases were the player saves while the program is in the middle of some function, like a pahtfinding function, a timer, or an animation.

I research coroutines and it seems like I can’t use them AT ALL if I want this to work. That’s a huge bummer because my AI routines rely on them extensively. I’m not sure what kind of overhead I will have creating my own timers and coroutine replacements.

And then there’s the biggest nightmare of all, making each function load data and pick up exactly where it left off. Seems like this will require a massive amount of extra code, and debugging will be difficult.

Take a look at the .net serialization system. It’s a nice standard way to mark classes and variables for serialization or no. You can also use one of the built in serialization targets, like serializing to/from bytes or XML or you could write your own.

Regarding coroutines, you should still be able to fairly simple store and use an enum state to handle this. Of-course not knowing your setup I can’t give direct feedback.

Will that work with iOS?

The serialization system just translates object into whatever data format you choose. How you store it is up to you. On iOS I’d say you have the choice between loading/saving the serialized data in your app data folder or sync it with an online service. If the latter, you’d probably want to do both.