best practices for saving game state

I know this is a common question among game developers, but could someone give me some advice on saving player progress?

I really have two problems with the information I’ve found so far. One, everything seems to recommend using JSON. I don’t understand JSON. I don’t understand how it differs from the file:write command. I don’t understand how it relates to lua files. I don’t understand any of it at the moment.

But never mind that for now. Let’s assume, just for laughs, I do someday understand how to use it. What I really don’t get is when I should use it. If you have a game that is a first-person adventure/puzzler, with lots of variables, mostly booleans, and a table for inventory, when exactly are you saving this data? Do I need to save any variable change or table addition the instant it updates? Won’t constant file writing slow down performance? And isn’t it a little redundant? You code smashedWindow = true, then you have to save smashedWindow = true again to a file? Can’t the system just assume that I want all variables saved?

I realize there is a lot I don’t understand here. And in that spirit, I’ll close on a really stupid question. Any app or game is saving its state constantly, yes? You exit, come back in and you’re back where you left off. Obviously, if you restart or clear the app from memory, it resets. Why can’t you just save that cached state to a file?

I feel like I’m missing some significant part of the concept here. Thanks for your help.

If you’re not concerned about losing state when the app is closed and relaunched, then you don’t have to save anything to file. It’s enough to just keep the data in memory.

What you should save to file is only the data that you want to make sure is kept between app launches. This is your persisted data. It could be things like player progress, statistics, in-game currency etcetera. It normally does not include things like smashedWindow, unless you want your player to get back to exactly where he left off after the app is relaunched.

JSON is just a data format that is very similar to how actual Lua tables look, which makes it easy to serialize/deserialize Lua tables to/from JSON files. Compare it to XML and you’ll probably understand why JSON is preferred.

Hi, 

Thanks for the reply. No, I would want to save everything. The player should have the exact same experience between sessions as they would if they played straight through. Small changes in scenes would be part of that. There are some variables that reset every time the player visits a scene, but there are quite a few that would need to be remembered. Should these be saved every time a variable changes? Between scenes? As I say, I’m really not grasping the whole concept here.

Ok, in that case I suggest you keep all the level data that need to be persisted in a one (or maybe a few) Lua tables.

To achieve what you want, you need to save every time you change any of those values. What I would do is probably create some kind of “level data handler” that wraps this functionality and saves your data to file every time you change anything. Then you could use it something similar to this:

local levelData = require("leveldatahandler") -- When game started levelData.loadFromFile() -- Set some value, this will automatically also save your data to file since you have implemented that in your leveldatahandler. :-) levelData.setValue("smashedWindow", true) -- Get some value if (levelData.getValue("smashedWindow")) then -- Do something here... end

Note that this was a very simple example. If you’re going to handle a lot of  data you would probably need to make the leveldatahandler smarter to get better performance and code structure. The fine thing about wrapping functionality into separate modules like this is that it’s easy to start with a simple implementation which can then grow more complex as new needs come up.

For our games ( also first person adventure/puzzle games ) we use GGData but will soon be moving over to Puggle fully ( I use it on my own personal projects ) - https://forums.coronalabs.com/topic/70253-the-puggle-framework/

As for when, we save when the player is going between the game and the main menu, when the app closes, and I believe between scenes as well but can’t remember completely now ( I haven’t had to touch that code in years ).

With Puggle, and GGData, you could do something like this:
 

puggle.data:set( "smashedWindow", true )

And then later, maybe in start up when initialising your scene, you could check to see if that window has been smashed and then update the artwork appropriately.

local windowIsSmahed = puggle.data:get( "smashedWindow" )

If your held inventory items is just a regular table you can store that out directly to Puggle in the same way, and the load it up just the same as well.

We also have our flags ( things like “windowSmashed”, “doorUnlocked” etc ) prefixed with the name of the scene they are in, automatically, so in the save file we would actually have “room1-doorUnlocked” and “room2-doorUnlocked”, so that we don’t have to think about naming the flags uniquely for each room.

Markus & Glitch Games,

Thanks so much for your replies. Both are a great help. I wish I could give you both a Best Answer.

GG,

A quick follow-up. Your approach - saving between scenes and when the app closes - is more or less the way I had envisioned it. I thought I had read somewhere, though, that iOS prohibits those sorts of actions on exit. I understand if you don’t recall the exact details of how you coded it - I seldom remember what I coded a week ago, let alone after years - but do you know if anything has changed with that? Or perhaps I simply misuderstood what I read before. Wouldn’t be the first time. Thanks again.

I’ve just checked, we save on both applicationSuspend as well as applicationExit, so not sure if Apple are OK with that but we’ve done it in each of our adventure games ( 8 so far ), fingers crossed they either are fine with it or won’t read this post  :slight_smile:

Also checked, we do save on scene changes.

Thanks for checking! And I wish you continued success with all your games.

And, Markus, thanks for helping to clarify things as well. I really appreciate it.

You’re welcome and thanks!

Also, if you are making a first-person adventure/puzzle we’d love to know about it so if you ever have any questions about these sorts of games, or want any feedback etc, please email me graham@glitchgames.co.uk 

No problem, just happy to help.  :slight_smile: Good luck with your game!

If you’re not concerned about losing state when the app is closed and relaunched, then you don’t have to save anything to file. It’s enough to just keep the data in memory.

What you should save to file is only the data that you want to make sure is kept between app launches. This is your persisted data. It could be things like player progress, statistics, in-game currency etcetera. It normally does not include things like smashedWindow, unless you want your player to get back to exactly where he left off after the app is relaunched.

JSON is just a data format that is very similar to how actual Lua tables look, which makes it easy to serialize/deserialize Lua tables to/from JSON files. Compare it to XML and you’ll probably understand why JSON is preferred.

Hi, 

Thanks for the reply. No, I would want to save everything. The player should have the exact same experience between sessions as they would if they played straight through. Small changes in scenes would be part of that. There are some variables that reset every time the player visits a scene, but there are quite a few that would need to be remembered. Should these be saved every time a variable changes? Between scenes? As I say, I’m really not grasping the whole concept here.

Ok, in that case I suggest you keep all the level data that need to be persisted in a one (or maybe a few) Lua tables.

To achieve what you want, you need to save every time you change any of those values. What I would do is probably create some kind of “level data handler” that wraps this functionality and saves your data to file every time you change anything. Then you could use it something similar to this:

local levelData = require("leveldatahandler") -- When game started levelData.loadFromFile() -- Set some value, this will automatically also save your data to file since you have implemented that in your leveldatahandler. :-) levelData.setValue("smashedWindow", true) -- Get some value if (levelData.getValue("smashedWindow")) then -- Do something here... end

Note that this was a very simple example. If you’re going to handle a lot of  data you would probably need to make the leveldatahandler smarter to get better performance and code structure. The fine thing about wrapping functionality into separate modules like this is that it’s easy to start with a simple implementation which can then grow more complex as new needs come up.

For our games ( also first person adventure/puzzle games ) we use GGData but will soon be moving over to Puggle fully ( I use it on my own personal projects ) - https://forums.coronalabs.com/topic/70253-the-puggle-framework/

As for when, we save when the player is going between the game and the main menu, when the app closes, and I believe between scenes as well but can’t remember completely now ( I haven’t had to touch that code in years ).

With Puggle, and GGData, you could do something like this:
 

puggle.data:set( "smashedWindow", true )

And then later, maybe in start up when initialising your scene, you could check to see if that window has been smashed and then update the artwork appropriately.

local windowIsSmahed = puggle.data:get( "smashedWindow" )

If your held inventory items is just a regular table you can store that out directly to Puggle in the same way, and the load it up just the same as well.

We also have our flags ( things like “windowSmashed”, “doorUnlocked” etc ) prefixed with the name of the scene they are in, automatically, so in the save file we would actually have “room1-doorUnlocked” and “room2-doorUnlocked”, so that we don’t have to think about naming the flags uniquely for each room.

Markus & Glitch Games,

Thanks so much for your replies. Both are a great help. I wish I could give you both a Best Answer.

GG,

A quick follow-up. Your approach - saving between scenes and when the app closes - is more or less the way I had envisioned it. I thought I had read somewhere, though, that iOS prohibits those sorts of actions on exit. I understand if you don’t recall the exact details of how you coded it - I seldom remember what I coded a week ago, let alone after years - but do you know if anything has changed with that? Or perhaps I simply misuderstood what I read before. Wouldn’t be the first time. Thanks again.

I’ve just checked, we save on both applicationSuspend as well as applicationExit, so not sure if Apple are OK with that but we’ve done it in each of our adventure games ( 8 so far ), fingers crossed they either are fine with it or won’t read this post  :slight_smile:

Also checked, we do save on scene changes.

Thanks for checking! And I wish you continued success with all your games.

And, Markus, thanks for helping to clarify things as well. I really appreciate it.

You’re welcome and thanks!

Also, if you are making a first-person adventure/puzzle we’d love to know about it so if you ever have any questions about these sorts of games, or want any feedback etc, please email me graham@glitchgames.co.uk