Save systems run the programming difficulty gamut from incredibly easy to ridiculously frustrating. As an example of the former, EEI currently saves the user’s progress through the campaign, and will display which level or “scenario” the player is on. While I did have to do some fiddly string manipulation, probably not for a very good reason, this was as simple as saving a single integer in a file and reading from it when appropriate.
Unfortunately, in-game checkpoints and quicksaves are at the far opposite end in terms of saving difficulty. The state of the game during combat is inherently complicated. This is not a case of simply saving a few values here and there, and resetting them. It’s a complicated process, which is why so many games have save bugs.
PPM (Project Perfect Mod) Forums:
For some reason I am unable to load my savegames, they crash the game. I can play for hours and do anything that I want even save, but when I load, I get a “tiberian sun has encountered a internal error” and it crashes.
Hi, I have an issue saving the game after playing a while.
After starting the game and loading a savegame I am able to save for a few rounds, but then the save game button is not clickable, I hear the button-click-sound when I am clicking on the save game button but nothing happens. What is worse… when I am trying to overwrite on older save game it dissapears after an unsuccessfull save game try.
Here’s a visual example from Portal.
Many enemies and projectiles will undoubtedly no longer exist when we revert to an older checkpoint. We need to extract the relevant, changing data from these enemies, while ignoring all the known information, such as the mesh. When the player reverts to a checkpoint, we need to clear all the projectiles, death decals, enemies, particles, and other accouterments from the scene. Then we need to re-instantiate these entities as they were.
Unfortunately, in a real game entities tend to keep track of each other. Those references are junk upon re-initialization, since they’ll point to a spot in memory that has nothing, or something random. We need to create a new system that tracks entities/GameObjects through an assigned ID number, then give the newly re-created copies the correct IDs.
We’re still not done. Many effects in any game are time dependent. The way they run properly is through timestamps, checked against the current time. Below is some psuedo-code.
if(Time.time – lastShotTimeStamp > _shotInterval)
DoShootingCode();
}
But the time for the program itself continues forward regardless of whether or not the player remains alive. As a result, when we recreate the entities, whatever timestamps they’ve created will be so out of date that whatever process they were gating will be instantaneously available. Essentially, every single time gated action that all of the projectiles and enemies perform is immediately glitched. Since all projectiles have a limited lifespan, that includes dying, which they do immediately upon restarting the checkpoint.
There are two ways to solve this. We can painstakingly search through all the various timestamps used by every single entity in the game, and set them forward appropriately upon restart. Alternatively, we create a layer of indirection when measuring time, and have this layer account for the discrepancy between the programs internal time, and the time perceived by the restarted entities.
I knuckled down and got to building this system, squashing each individual bug one by one, before I just stopped and decided to shelve the entire thing. There’s just no way to magically have a checkpoint system that works when the data changes, and the data is very likely to change during development. Every time the data changes, the load/save for the entity must also change. Furthermore, a checkpoint system inside each battle is a minor feature anyway. There’s no sense in wasting so much development time for this one feature.
So instead I pivoted to improving the user interface, specifically making the state of the weapons more immediately clear. Modern shooters tend to put as much information as possible on the targeting reticule itself. This makes sense, since the player’s eyes will always be in the vicinity of said reticule.
I decided to throw something similar into the game, and made a quick video of the effect so you can see it in action. I think it looks quite nice, and as a result the obfuscating bars over the avatar are gone.
For those curious, the effect is created entirely in a shader, including the nice little spaces that you see representing individual bullets when a weapon with a magazine is selected. The shader is clever enough to automatically adapt to any arbitrary magazine size, as shown in the video.