Best practice when unable to save game progress

Best practice when unable to save game progress

My games are using file system to save game progress (using FileUtils::getInstance()->getWritablePath(); and FileUtils::getInstance()->writeDataToFile). The savegames uses about 100k space.

On most devices everything is fine, but it appears on about 1/1000 devices that it does not work (Android only). I did a lot of debugging and what happens is that sometimes, the file end up 0 bytes. Sometimes, only half the save game was saved and so ending up with a corrupted savegame. Sometimes, it just does not save at all. It seems that it is related to either no space left (or out of inodes, but it is the same error message). Sometimes it is “no permission” (even though I am using internal data storage which I do have permission of course). Also, sometimes after a min or 2, the game suddenly start being able to save the game progress or can do it intermittently.

So the end result is some people will not notice it because it can start working again a bit later, some other less fortunate end up losing their game when they come back.

I tried a lot of different way to make it work, I tried doing a fflush before fclose, tried multiple retries, increasing buffer, nothing worked. I also keep 3 save games. So if one becomes corrupted, I have the previous one. But when the device cannot save at all, it does not help. I ended up showing a big warning message to the users when I cannot save the game asking them to cleanup some space.

So my questions are:

1: Is this normal behavior? Am I the only one facing this?
2: What do other games do when they cannot save the progress of the game? What is the best practice?
3: Would saving on game center/cloud remove this issue and make it more reliable? What if I face the same issue with game center, what should I do?
4: Any other best way to save progress that will ALWAYS work?
5: Other?

Thanks a lot.

I use SQLite for saving my games data.

Or UserDefaults is another option.

Use SQLite. I think this is a best solution for saving games.
Using files for saving generate issues when you update your game and you need to add some other data to save and you should have a separate files for every version.

Thanks a lot. I guess I will have to look into it. A few followup questions:

1: Do you use the sqlite as a storage mechanism or as a real time data fetching mechanism? ie, do you load the game data all at once as the game starts and only use the in-game structure data for the whole game session and only save into the SQL any changes you want to keep for the next session? Or do you real-time fetch the data from the sql DB during the game session and reading/saving all the time? (Hope this was clear).

2: How does it compare to Cloud save/game center online save? Are they 2 different approaches or we can use both together so people can share the data between devices?

3: Is there any possibility that the DB/device storage runs out of space and the same issue appears? What do you do in that case?

Thanks a lot

This is my opinions.

  1. At game startup, I do the following:
  • check to see if a database already exists. If yes, player has played my game before. Load the data into a few classes that my game uses.
  • if no database exists, they have not played my game before (or they deleted it and re-installed), create a new database with some defaults to start. Load the data into a few classes that my game uses.

as the player plays the game, update these classes and these classes in turn update back to the database.

when the game ends, make sure there is no mare data to save, close the database, exit

Next launch, repeat these steps.

  1. I don’t use any saving to the cloud services, etc. My games are designed for this. My games are quick, single player, quick-fix games.

  2. Sure devices can run out of space. Perhaps your app gets hit by the lack of space, maybe not, depends on how much game data you are saving.

My games (a few very large) only store about 1mb of data.

Hi, I just did some reading on sqlite on android and it looks like at the end, the DB is still a file stored locally on the “getWritablePath()”. So I am not sure that would fix my problem since it is still, at the end, a file being saved and I will still get the “no access” or “no space left” message the same way I get from my current savegames being saved. Does it make sense?

You can’t do much about this situation besides notifying the user about the lack of free space. Have you considered doing the check at the start-up of your app for the approximate amount of space required, and displaying a message to the user at that point if there isn’t enough free space?

If you wait until you actually need to save data before doing this check, or not doing the check at all, which results in an error on saving the data, it would most likely have a negative impact on user experience. It’s best to notify the user as early as possible before they end up losing their progress in your game as a result of an error.

1 Like