Save format rewrite

Posted On 6 May, 2018

In the game development industry, it is essentially guaranteed that at some point in your project you will look at the entire thing and realize that one of the most core components, central to the entire design, has simply been done wrong from the beginning. Depending on budget, or more often leadership and partner deadlines, it often then becomes a choice for the development team: Do we put an ugly bandaid on this feature and release it as-is, knowing that it is wrong? Or do we invest a significant amount of time and effort to drastically change the direction of development at such a late stage?

Conveniently, our team is tiny we have no release date and nobody can force us to release anything we don’t want to, so we have the luxury of doing things the right way, even if it means spending extra time rewriting something that has already been written. I suspect many other gamedev teams are jealous.

The issue I have been working on lately is one that we really need to get right before release: the issue of save formats.

The philosophy of a save

What data goes on disk, and what gets forgotten really is a sort of arbitrary thing once you distill away all of your preconceptions about the subject. As it turns out, there does not exist any universal thing which encompasses the idea of saving a game. When we first built the engine, I approached the idea of game saving from a perspective that was familiar to me and which seemed to work at the time, without really considering the big picture. As a result, some problems started to pile up.

I am sick to death of broken save files so for the next update I’ve decided to confront the philosophical problem of game saving head on. I didn’t invent the idea of saving game progress. When I make designs, my brain tends towards familiar tropes and patterns I’ve seen so many times before, and I think I used the wrong one when I initially wrote progress saving in Zero Falls. So now I’m taking a step back, deciding how saves would function in an ideal world, and making steps to move it there with this update.

The linear story save

The save format philosophy we have right now is one that follows a perspective of the story being a linear sort of thing, and the character existing inside that story. Every second of gameplay is just an advancement of the narrative of character and world together, and when you press “save” you are freezing the game at a moment of time to resereve the option of returning.

It makes a lot of sense because we have linear quests and dialogues. If you talk to someone, and they give you an item, you should be able to reload the game at a time before you talked to them and you will expect to no longer have that item. You’ve gone back in time, so to speak.

It really is a classical formula, and it has worked in so many story driven open world games before that it was the natural thing to design if I was going to make a design without thinking ahead…but it has issues.

Here’s a list of issues (because I gotta have at least one list)

  • You simply can’t make an ideal solution for persistent unlocks that live outside the save file
  • It makes a very fragile data format that allows the entire game state to be corrupted by a single missing bit
  • Being able to go back in time means making a copy of the world, and our world format is huge
  • You have to write scripts to upgrade the entire save file when a story element changes in part of the world which was already recorded
  • Most importantly: character progress is always tied to world progress.

That last point is the big one, and it’s kinda the same point as the first one. Our game world is the same thing as our character, and yet there’s reason to think it shouldn’t be. In a game about exploring and collecting unlocks, some people will want to ditch their world after a long play session but keep their unlocks, and others will want to start fresh with every world. How can we as developers give them that choice?

I think we need to look at saves from a different perspective.

The world and the character

In hindsight, this format seems more common among modern open world games, and after reinventing the wheel myself I think I can see why.

The idea is, character and world are separate entities. Character moves freely between worlds, and neither world nor character ever makes an explicit copy of itself in the form of a traditional save file. Instead, both make progress in only the forward direction, and if the player wishes to return to an earlier state of progress it is possible to create a new world or a new character or both.

This format gives up time travel in favor of granting the player absolute power over which progress to keep, and when to experience something from a fresh start. It allows both characters and worlds to serve as trophies and momentos of past acomplishments, while removing the hesitation of starting over again. More importantly, it solves all of the problems I listed above and empowers me to make future changes that might be fun.

I also realize that while I never adopted this save format, over the course of development the game has always evolved towards a feature set similar to other games that use the same save philosophy. You don’t lose any progress on death in Zero Falls, a featue which rarely coexists with the ability to load the game to a previous point in time. Also the procedural nature of our universe, popping into existance the first time you look at it is a concept which creates fundamental architectural problems when you allow time travel. You may recall a bug where stations were duplicating themselves? This is only a symptom of the bigger issue at hand: how does a procedurally generated world return to a state before it generated without creating a mess? The answer is with endless hours of debugging and frustration, as well as very long loading screens and very large world save files.

I think the final game needs to adopt this save philosophy, even if it is a little painful to transition, and as such I am making the change right now.

What’s changing

I’m gutting the save format. Your existing saves will be useless after the update and you’ll have to start fresh. Sorry about that.

I’ve build the new character progress system around an SQL database. It’s lightning fast, and your data is always on disk so it will be very hard to lose character progress. Even if the game crashes, you will find your inventory and credits and research is all up to date when you get back into the world. What’s better is that data saves when it changes with zero lag, so no more waiting for long auto saves after every time you dock, and no more worrying that your progress is safe.

As for world crashing, being able to completely remove all binary data relating to characters frees up a lot of room to make world data more durable. We can regenerate sectors if they have a really bad issues, and we can throw out a quest if it is causing problems, all while leaving the world intact and the game running. This means absolute worst case is you lose the ability to complete a quest, but remember you will also have the option of taking your existing character to another game world and attempting the quest again.

Overall I recognize this will be an awkward transition for some, but this is early access after all. I plan to leave in the code that handles traditional saving (the time travel type) however I will be discontinuing support for that functionality and probably hiding it behind the debugging mode.

It will be nice not having to worry about time travel paradoxes when writing quest logic.