Save and Load: A Developer Tool
August 4, 2017
The second last technical piece of the Robyn HUD puzzle has fallen into place this week. Namely the ability to save and load games. Freely saving and loading the game state is tremendously useful for developing and debugging games. It’s also something that’s difficult to implement early in development when the minute details of the technical requirements of the game are only vaguely defined.
When I first started playing computer games years ago I tended to take save games for granted. My game type of choice was adventure games, which naturally evolved into the development of the Sleuthhounds computer game series. In those classic adventure games from years past you were free to save your game pretty well anywhere. I didn’t even think about how useful that was until I ran into other types of games that used the (shudder) dread checkpoint system. Suddenly I was at the mercy of the game developer. If they didn’t put a checkpoint close enough to where I was or they had some monstrously complex, difficult, or long section of the game to get through before the next checkpoint you were screwed. If your character died or if you had to leave to do stuff in real life you could lose a lot of progress. I knew right from the very first checkpoint game I encountered that if I ever made a game I’d implement saving and loading properly, which is to say being able to save and load at any point.
Fast forward to today when I am making my own games and I still adamantly believe players should be able to save wherever they like. Saving at only certain checkpoints is the equivalent of giving a person a book and telling them they can only put bookmarks in on specific pages. The tricky thing with being able to save anywhere is it’s much more difficult to implement from a developer point of view than a checkpoint system (which could lead me into a whole development rant that it’s a developer’s job to make software easier for people to use than making it easier for the developer to develop, but I’ll spare you all of that, faithful reader).
What makes saving anywhere so difficult is the variety of data to keep track of. For example, if you have a game where a character can jump through the air in an arc, then to perfectly save the state of that jump you’d need to save the character’s position in space, the velocity at which they’re moving, the frame in the animation that the jump is on, the position in any sound effect playing as part of the jump, and probably one or two other bits of key information. And that’s just for one character doing one action.
In order to save anywhere you need to have a good sense of all the data that your game needs to track. You can only get that sense when your game is significantly evolved from a technical standpoint. That’s where Robyn HUD has now gotten to. The technical side of the game engine is robust enough now and the data is stable enough to make it useful to save. While the data requirements of the game were still in a large state of flux there wasn’t much point in trying to implement save games because those games would most likely become invalid as the data the game tracks would change.
Before dealing with saving and loading in Robyn HUD I first dealt with that same challenge in the Sleuthhounds games. For all my talk above about fully saving the state of a game, with Sleuthhounds I was able to make several simplifying assumptions that provided a “good enough” saving experience without involving the full complexity of a truly full game state save.
Sleuthhounds is very much in the vein of traditional point and click adventure games. From a technical point of view, that means that whenever the player initiates an action in the game a brief cutscene of that action is shown. If the player wants to look at a painting, then the player’s character might run a brief cutscene consisting of saying a single line of dialog. If the player wants to pick up a fork, then the player’s character might run a cutscene consisting of an animation of the character leaning forward, taking the fork, stowing it away, and then saying a line of dialog. Or the game might have a longer scene where two characters are saying lines back and forth and animating as well.
In contemplating the saving for Sleuthhounds I took a step back from the general problem of how to save all of the data and thought about when the game would need to save data. While a cutscene is running the Sleuthhounds games temporarily block access to the menu system, meaning that players themselves can’t initiate a save during a cutscene. That in turn meant that it wasn’t necessary to save the point within a line of dialog or a specific animation that characters in the game might be at because it simply wouldn’t be the case where the player would be able to save when those actions occur. Since the cutscenes in the Sleuthhounds games are short, the player doesn’t realize they can’t truly save everywhere (at least, I hope they don’t realize that).
Apart from the player being able to save only when a cutscene wasn’t running, I also wanted the game itself to be able to do progressive autosaves. This was a desire that stemmed from using my rather flaky laptop. That computer will work fine for days or even weeks on end and then just out of the blue it will hang. Since I was doing part of my development on that machine I didn’t want to lose play testing progress so I very much wanted the game to be able to autosave at certain points. The question then was what those points would be.
Most modern games nicely autosave when you quit the game, so I knew I wanted to do that. As for other points to autosave in a game the logical choices were either right before or right after a cutscene ran. From a game development standpoint it seemed a better choice to save before the cutscene. That way if anything “bad” happened during the cutscene that messed up the game I could restore to the autosave and debug the bad situation. Combined with the game autosaving on a quit it also meant that player’s wouldn’t lose any progress in the final stable build of the game.
The one hole in the saving system for Sleuthhounds was that players could force the game to quit during a cutscene by hitting the standard alt-F4 shortcut key or by tasking out to Windows and killing the game from there. In either case, the game treats it as a quit and informs the player that their progress will be autosaved. If the player ends the game in this manner when not in a cutscene the game does indeed autosave as normal. However, if the player end the game while in a cutscene the game actually does…nothing. It still pops the message to let the user know an autosave will occur but then it just quits afterwards. The reason it quits is because while a cutscene is running the last autosave made is the one right before the cutscene and there’s no reason to overwrite that. The player can come back in later and initiate the action that started the cutscene in the first place a second time. I figured I could get away with this because it was an extreme case for exiting the game that in practice wasn’t likely to happen often if at all.
Saving when the player can access the game menu (i.e. a cutscene isn’t running), or just before a cutscene starts, or when the player quits was all well and good for Sleuthhounds. However, when it came to Robyn HUD I needed to up the sophistication of the saving. Unlike in Sleuthhounds, In Robyn HUD it’s possible to have multiple “cutscenes” running at the same time (they’re not really cutscenes but for the sake of this discussion that’s what I’m calling them). In Robyn HUD perhaps two guards are talking in one part of the level while Robyn and HUD are talking in another part. While the game is running the two cutscenes progress simultaneously. One doesn’t wait for the other to finish.
From a saving point of view this presents a challenge. While it’s still possible to save whenever a new cutscene starts, the challenge exists with how to save the state of another cutscene that is already running at the time the new cutscene starts when characters may be moving around or may be in the middle of a line of dialog. To handle this, Robyn HUD now keeps an internal track of the “action” that a cutscene is at. On a save, in addition to all the necessary state information for things like the position and orientation of characters the game also saves the count of actions that have run for each currently active cutscene. On a load, the game then requeues each cutscene and skips over the counted number of actions, which places the game roughly back to where it was when the save occurred.
I say roughly because the game treats actions as atomic. An action (such as saying a specific line or walking to a specific point) is considered to be either fully done or else not yet started at all as far as the save games go. So if a save happens while a character is in the middle of a line of dialog, then reloading that save with have the character start saying that line of dialog from the beginning again. This is a simplifying assumption similar to the ones used in Sleuthhounds just at the finer level of detail of individual actions instead of whole cutscenes. As well, I feel this actually provides for a better user experience for the player. It can be jarring coming in on a line of dialog in the middle of a sentence and even moreso if it’s in the middle of a word. By treating that line as one action that must run from its start it ensures the entire dialog line is heard when the game is reloaded.
All this work to allow the game to be saved freely at any point is obviously helpful to the player, which would be a strong enough argument for doing it right there. However, it’s also beneficial to me as I develop the game. Being able to quickly save and reload the state of the game at any given point allows me to make tweaks to the game scripts and see their effect without having to replay the entire game to that particular point. To debug parts of the game and to get the little nuances right I need to be able to replay individual scenes over and over again. The more easily I can do that, the faster the development of the game as a whole goes.
Saving and loading was the second last missing technical piece for Robyn HUD. With it in place almost all of my attention can shift to creating content for the game now. Laying the foundation for any game takes a while but if you do it properly you reap the rewards later on. And what of the very last technical piece outstanding? It concerns facial animation and dialog lip syncing in the game. Since I haven’t recorded any dialog for the game yet, that last technical piece isn’t high on the list of priorities at this time. As such animation will be tied to the lines of dialog characters say and as the save system handles dialog lines already, I’m not concerned that the animation will have a negative impact on the save files. So onwards to more game content!