How do people design the save game feature in large/complex games?

1.10K views

The save game feature seems simple but it’s mind-blowing how it can return the exact state of a game with all elements/events organised in the correct order. Can anyone explain how it works?

In: 668

39 Answers

Anonymous 0 Comments

When programmers make a game, they typically think of the logic in relatively easy to digest chunks, called objects.

Objects typically have a ‘template’ called a class. Each object would have its own state. So, the player object may have a position represented by x, y coordinates.

Storing an objects state in text is called serialization. Remember, all the logic is on the class in the source code. So this greatly reduces what needs to be stored in the state.

So player.serialize() could return a string like “player,1,45” meaning this player has the position of x=1,y=45. If you have a facing variable you could store that as well, maybe N,S,E, or W. “player,1,45,E”

The template (class) would also have logic to go in reverse, to deserialize. So, take a player string and rebuild the player object from it.

So maybe you have an Enemy class that has an ID, x, y, and facing. The ID doesn’t necessarily need to persist, so you can serialize them to just be x,y, facing as well.

You loop through the enemies:
For each enemy, use the serialize method. Put the strings together in a reversible way.

“player
1,45,E
enemies
2,4,S
3,7,N
5,5,N

This is the save data. Maybe it’s minified or obfuscated on your system using some algorithm. Such as “f87Ax4” maybe reverses to give that string back.

Because of the chunking in software development, it’s easy to modify the Enemy class to add a new state variable, like type, and have it be handled by serialize method. Theoretically, no other code needs be changed.

You’ll also probably need the version the save was created on. Then they would need to add logic to handle loading each older version of save data, and typically updating them with a migration.

“V1.0
player
1,45,E
enemies
2,4,S
3,7,N
5,5,N“

Needs to be migrated to
“V1.1
player
1,45,E
enemies
2,4,S,melee
3,7,N,melee
5,5,N,ranged

Hopefully this is enough so you get the idea and how they more easily build upon it to ultimately store the entire game state.

Anonymous 0 Comments

As you go through the game, for it to function normally without saving, it has to keep track of what is done and what isn’t through flags. Saving is simple — it’s just a snapshot of what exactly is already done. The part of the code that loads graphics for example isn’t needed, so that and other parts are lopped off from the save. It’s really the design of the rest of the game that naturally supports saving

Anonymous 0 Comments

Let’s say you have game of tic tac toe and you want to save the board state in a file. The board is 3×3 large and let’s say zero equals x, one equals o, two equals empty.

You could save the board by going from left to right, top to bottom row:

220202022 then represents this board:

“`
X
X
X
“`

OK you just made a file format for tic tac toe. Other games do the same but just include more data. Let’s say you defined a specific order of saving for example

1. The version of the save format
1. Dialog options you took
2. Items and their position in the inventory
3. Amount of gold you have
4. Your username
5. Your x, y and z coordinates
5. etc.

Now you just go like before from left to right and save each thing with a value et voilà you persisted state.

Write a loading screen that reads said file in the exact same order and you have your state back.

Anonymous 0 Comments

Wait till you figure out that an undo/redo system basically means saving and loading the game at absolutely any and each step that you take. Games like Factorio even combine the two, where you can chose to have a replayable savegame, essentially recording your every action, for video-like playback. This is achieved through carefully designing the data model for actions and states.

Anonymous 0 Comments

In general, programs have variables. If you’ve ever done algebra you might have an idea of what variables are, except in programming variables be several types. A string is any arbitrary word or phrase, an int (or real or double – depending on programming language) is a number you can do math on, or check things like greater or less than, and there’s a boolean which is either True or False (1 or 0, Yes or No).

The example I always give is Zelda, how you name your character is a String, how many rupees you have is an int, whether you have beaten the first level is a boolean.

And then this data is all saved. Except it isn’t just saved to a text file (usually) because they don’t want people just editing the text file to cheat, so they encrypt these variables in some way in the file and decrypt when they load your game.

Keep in mind you’re keeping track of a lot more than a few variables. Every enemy has an x and y coordinate, a health value (0 to 100), any other important stats, etc.

Anonymous 0 Comments

There are many ways.

At one extreme a saved game is nothing more than a memory memory dump. You take all of the bits that are in memory and write it to a file. When you reload the game, you are just loading that saved state into memory again. It’s easy to implement and is perfect. The drawback is that the save file is generally measured in gigs. This is exactly how “quick resume” works on Xbox.

At the other extreme you have “saves” for read-only cartridges. The game can’t keep any records of what you’ve previously done since it can’t write anything to storage. If you only care about what level you are on, the health bar and number of lives when you started the level you could encode that information in just a few characters. For carts where there is no save file at all, you just encode relevant information for resuming the game in something like an 8 character string.

These two extremes are the only two trivial solutions. Everything else takes effort.

The other methods require you define what information is important to keep and what information is not. For example, the location of an NPC might or might not be important for a game save. These games can maintain a database of records of state and events that are important to keep such as items, NPC conversations, completed quests, locations of moveable objects, changeable stats, and such while they do not keep information that is not important to keep.

Anonymous 0 Comments

A simplified version. When you are playing, the computer has data called “state” loaded into memory which captures where you are, what’s in your bag, what has happened in your environment, etc.

All they have to do then, is move the state data from memory to disk, and when you restore they load it back into memory.

Anonymous 0 Comments

In order for a game to even run, it has to be able to answer – and update the answers to – a variety of questions. These questions are things like:

* Where is the player? (I, the console or computer, need to know this so I know where to draw them.)

* What’s the player’s name? (I need to know this to fill in text boxes properly.)

* Which door did the player last come through? (If they die, that’s where I’m going to respawn them.)

* Which bosses has the player already killed? (I need to know this so I can determine where certain NPCs are, which quests are available, whether certain doors are or are not unlocked, etc.)

* What items does the player have, and if they’re consumables (bullets, medpaks, PokeBalls, etc.), how many? (Can’t let you buy arrows if you don’t have a bow. Can’t let you shoot them if you’ve run out.)

…and so forth.

The answers to these questions are stored in the computer’s “short-term memory” (more technically known as RAM, random-access memory) as “variables” (since they can vary as the game is played), and the game references these variables whenever it needs to answer (or change the answer to) these questions.

Since this is the case, and since these variables are *necessary* to play the game in the first place, it’s fairly straightforward to design a subprogram that collects all these variables from RAM and stores them somewhere else – like, say, the computer’s *long*-term memory (i.e. the hard drive). If you couldn’t do this, any time you reset the computer’s RAM – by turning it off, playing a different game, or loading a different save file – you’d have to restart the game from scratch (as indeed you do have to on some really old games like Super Mario Brothers). To load the game, you simply have a subprogram that grabs the variables back from wherever in long-term memory they were stored and puts them back in RAM in place of whatever’s normally there when you start the game afresh

.Even for really large and complex games, however, variables only make up a fraction of the code, and the code in a modern game, however complex, only makes up a small fraction of the game itself – *most* of a game’s file size is things like maps, graphics, animations, and audio files. As an example, the actual *code* for unmodded, original Skyrim (the .esm file) is about 240 MB; the whole game is about 5800 MB, and the save files vary in size but are generally around a paltry 6.5 MB each. As a further example, Skyrim mods that *only* change code, even those that change it extensively and create new subsystems for the game, etc., are generally less than a megabyte; mods that change or add graphics can quickly get into the dozens or hundreds of megabytes.

**Tl;dr:** When you save the game, you’re essentially taking a list of answers to questions the game has to ask while you’re actively playing it. Since the list of answers already exists and since it’s a vanishingly small fraction of the actual game itself, it’s easy to write it to a file.

Anonymous 0 Comments

Games live in the random-access memory of your computer. Every bit of information required to create any specific game state is stored there. The simplest way to save would be to just copy all of this data to the hard drive so it can just be moved back and resumed later. But this would take like eight gigabytes of hard drive space for each save, so you need to optimize the save format for space. This means discarding any information that is not relevant for tracking your progression- like art assets, which stay more or less the same, loaded areas, all that stuff that is made to be easily recoverable from the game data, so you don’t need to copy it into the save. The only thing you really need to save is player data- what you’re carrying, where you are, what quests you’ve completed. And that can be made very compact.

Anonymous 0 Comments

Let’s imagine a completely arbitrary game and estimate some costs for it.

Let’s take a multipart quest of “go to town, locate person, find person’s lost burrito, return to person, deliver half-eaten burrito to landfill…etc” which can be imagined simply as “step x of 99.” So even though the list looks complicated, if the program writes a “05” somewhere, the game knows you’ve completed the first five steps and can build the world accordingly (person likes you and chooses the nice dialogue options, burrito is not on map, landfill scavenger population is set to “high,” etc.). So our quest state can be stored with two decimal numbers and still have a large impact

player/chest inventory can be more impactful, but still not hard. If you have 16 slots in your inventory and the game has 99 items (plus 00 to represent empty), then an entire inventory can be represented with a mere 32 numbers in a row. Yeah, we probably need to do this for a lot of containers, but sometimes some big games cheat and only calculate container inventory if the player has interacted with it before (this is one reason later game save files are sometimes much bigger than early game ones)

player position can be as simple as “we’re at save point #7”, but let’s assume a more complicated game that requires something like “we’re on map #12 at position (1337,0420)” which is still only 10 numbers. And since NPCs often stay at one point (or have a behavior the game can calculate without relying on a save file), they don’t need to be included in the save files for a lot of games unless they are dead or something. Just save a time variable and know that NPC A is at the bar at that time.

Everything that seems complicated can usually be broken down into just a few numbers with the right kind of forethought, and lots of more complicated things only need some slight input from the save file to construct a drastically different world. As long as you know which block of numbers represent which game info, the game just needs to think a bit to build the world around it.

Putting things in more perspective: this post has about 2800 characters in it. If I converted all of them to numbers and used the rules up above. I could represent 80 16-slot containers of items and 100 different quest states with space left over.

Let’s assume a hefty save file is 100MB (based on a Dyson Sphere Program file I found on my computer). One unicode character is one byte. That means we can store 107,374,182,400 numbers worth of data in the file. Even if our game has something absolutely ridiculous like 1 million quests and 1 billion containers with 16 slots each that fit the above definitions, we’ve barely used a third of our entire save file space, and that’s even ignoring the fact that you can get even more efficient by breaking things down into binary or hexadecimal rather than relying on unicode