July 19, 2013

Saving data

Hello everybody,

Today, I'll speak about... saves! So this post won't have a lot of screenshots, mainly boring text ;)

Not very impressive, but here is the save menu!

As I want to be able to build up a complete version of my game as early as possible (even if it's only on 1 level), I have to implement eveything the final game will need. And recently, I thought about the "game over". What happens when the player fails?

I - Problems

Well... This question is a lot trickier than it seems. Because when the player fails, the game must bring him/her back at some point where (s)he is OK.Thus... we must save this "some point where he is OK". Hence a few questions come up:
  • Does the player choose when to save? If so, he can ideally save whenever he wants, and there is absolutely no difficulty to the game. Moreover, technically, this means being able to dump everything that is in the RAM, resulting in hundreds of Mo of data (maybe many Go). This makes the save and load process rather slow. And by the way, who cares about the exact position of a bird in the sky that you may not even have seen?
  • What happens if the player saves during a battle? How to manage all the timers, the physics engine running in background and all the objects in an unstable state? What happens if the player saves when (s)he's dead? (Yes, there are some games where it's possible...)
  • If the player doesn't choose when to save, does he still control the saving process? That is to say, are there some visible "checkpoints" at which the player can save its game? 
  • The other way around is that the computer manages everything and performs automatic saves completely hidden from the player. But in this case, it means that if a crash occurs, the player may totally lose his game. Moreover, if many players try the game during the same period, the game should be able to manage different "profiles" in order to accept different players.
  • If the computer manages the saves, I don't want them to happen everywhere. I have to chose some "safe places" (ie without too much interaction around) and at strategic points (beginning/end of a quest, before difficult parts...)
  • There are some games where, when you die, you don't go back to your latest save, but to some automatic checkpoint that you didn't even notice. This avoids a lot of frustration to the player if it's been a loooong time that he couldn't save. But of course, if you quit the game and you come back later, this automatic checkpoint does not work anymore. You start from your last save. Is it an interesting mechanics for my game?

Hence, those questions sum up in "when, what and how do I save?"
  • when: everywhen vs checkpoints
  • what: everything vs only a few states (player position, inventory...)
  • how: player vs automatic

And there are some more-or-less inevitable links, for example: everywhen => everything, automatic => checkpoints, everything => slower and space eater, automatic => difficult crash recovery, ...

II - My chosen solution

So I considered using some kind of "old-school" save system: There will be checkpoints, and the player will manage saves him/herself. At the moment, I allow 5 save slots for testing purposes but this number will likely raise. Here are the main advantages:
  • This enables many players on the same computer, and/or many different saves (I usually liked old games when you could keep a save just before a cool boss). 
  • The saves will be dumped on the hard drive in different files (slot1, slot2, slot3... etc). Hence, one can copy-paste saves to keep them after removing the game, 
  • It's also possible to share saves with friends!
  • It enables to have various saves in case one crashes
  • Furthermore, this system may be compatible with some "automatic checkpoints" too. Maybe I'll add some at any point where I don't want a "game over" to be too harsh.

III - Implementation

While implemeting this system, I had lots of problems, especially with regard to the software design (I'm not that good in software design). I won't detail everything here, but amongst other (this is a bit technical):
  • The "save" data is implemented with static attributes (some kind of "singleton class"), which enables me to easily reach/modify it from every object in Unity. As soon as the character makes actions/complete a quest, everything is registered in the save object.
  • At save points, I dump the save object on the hard drive using XML serialization, but, static attributes are not serialized, I had to code this myself.
  • Hence, that means there is only one "save" object in memory everytime, which is problematic when you want to list all the saves that are accessible from the hard drive... Because when you want to load a save, you want to know what's inside. This means the game has to read them all, and display a few relevant information (place, time played, inventory stuff...).
  • The dumped files may be edited with an hexadecimal editor... I tested it, and it seemed I corrupted the file, so I had to add some kind of validity check before effectively loading a save.
  • And of course, I also had all the classical problems of GUI: menu navigation, font and button resizing, toggle character control when you're in the menu, differentiating main menu and in game menu...

Well , that's all for today! See you next time guys!