Are there any recommended practices for datastores? I’ve noticed that very, very, very occasionally my game will not load my data and then it’s gone. I was wondering if anyone’s made a guide on how to combat this?
Don’t you just make a repeat loop until the DataStore returns the data? If you mean combating data fetch failure, that’s out of our hands. Roblox handles that stuff.
As advice goes, that could be better. Hopefully the following helps both of you.
Avoid repeating requests, Roblox automatically does this for you so you don’t have to. Furthermore there is no guarantee that any amount of repeats will eventually succeed, infact you’re going to use your request limit up and have to wait before making any more.
Request failure should be handled by you. If a players data fails to load then you need to handle this, you don’t want to overwrite their existing data with new data if their existing data was more ‘valuable’ (eg. they have more currency.)
There are plenty of other points of failure that you need to take care of too.
- Unable to save after a player purchases an item.
- Unable to save after a long period since the previous save.
What’s the recommended way to handle these errors, then? Is it as simple as displaying to the player that their profile failed to load, and they should rejoin the game?
These are some general strategies developers combine to overcome some of the issues.
- Transparency - Always tell the player what’s going on, if there is an issue make them aware of it.
- Auto-save - Unless your game requires players manually save then you should automatically save their data over some interval, usually I choose once a minute.
- Purchases - Don’t let a player do something if you can’t handle the data correctly. If a player is purchasing a product, fail the purchase.
- Resourcefulness - Don’t make requests you don’t need to. A lot of developers try to be clever by saving all the players data to one key so they only need to make one request to load/save.
If data fails to load then I would advise that you allow players to continue playing, but don’t save their data and make sure they are aware of this.
Thanks for all the help
Usually when I’m creating player data profiles I’ll store it all under one massive table and have sub tables to represent different compartments of their inventory. As far as autosaving goes, I tend to save their profile when they leave the game however I feel that this can potentially be risky if the server is shutting down (you’re the last player leaving). So, in the future, I’ll try to save player profiles per inventory change. Thanks a lot for the help
That’s not true.
Everything else is coolio tho
I was under the impression they were, regardless they should be eventually and thus my point remains.
I’m not sure it does remain because the premise isn’t true? As of right now you should definitely add in a retry feature, given that from what I can tell (you might know better obviously as you’re an intern) no one is working on this, and if they are they haven’t announced its near to release.
Its a fairly small thing to script too
Do not just re-initialize a player’s data when a DataStore operation fails.
If you can’t retrieve a player’s data, you can probably just kick them and ask them to try again at a later time.
(I would also like to plug Stravant’s PlayerDataStore module. It provides a neat interface for Roblox’s DataStore, which would make it more intuitive for you and thus less error-prone)
You probably already do this, but be sure to have Player:WaitForDataReady() before you do anything with Data Stores / Data Persistance.
I’m hoping that work on automatic retry is eventually continued, but it’s easy to see where @woot3’s confusion comes in. As you said yourself, communication on that front was a bit iffy there for a while.
No. This method is deprecated and entirely unrelated to datastore service, there is no reason to be using it anymore.
Ah, alright. I never knew it had been deprecated.
In most cases, data is stored on a per-player basis. Assuming a player cannot be in more than 1 server at a time, these are some things I’ve done:
- Load the data once when the player joins. Once loaded, store it in a table so that you don’t have to retrieve it from the DataStore again.
- When you update data, just update the data in the table for the player. Don’t save it to the DataStore.
- Save your player’s data to the DataStore on three occasions:
- When the player leaves
- When the server shuts down
- Auto-save loop (frequency is up to you–I usually stick around 1-5 minutes)
- Wrap your calls to DataStores in
pcall
since they are not guaranteed to succeed. - Inform the players if DataStore requests are failing (e.g. “Sorry, Roblox is unable to save any player data at this time.”)
I made this example a while ago, Best data saving technique? - #15 by Tom_atoes
The data doesn’t take many requests but it will only save on leave.
I’ve noticed that very, very, very occasionally my game will not load my data and then it’s gone
The biggest and easiest mistake to make with the DataStore is this:
game.Players.PlayerAdded:connect(function(player)
myDataTable[player] = load(player.Id)
end)
game.Players.PlayerRemoving:connect(function(player)
save(myDataTable[player])
end)
What happens when their data fails to load? Kaboom, when they leave the place the PlayerRemoving function will dutifully save their currently nil player data to the data store erasing their current save state. It could happen even if it doesn’t fail to load too, if they “bounce” and end up leaving the game immediately after entering it (This happens way more than you would expect, a good 10% of players end up bouncing IIRC) then it’s possible for the save to happen before the load completes. Though to be fair, this many not be your issue, since it would probably fail more than “very very very occasionally” if it were written that way.
If you don’t want to worry about stuff like then you can use my PlayerDataStore module and it will do it’s best to make sure that a player’s data can never accidentally be erased. Note that it doesn’t provide any interface for error handling (Intentionally, since the interface it exposes is too simple to provide reasonable behavior in the case of datastore failures other than simply grinding to a halt. Though I could probably rewrite it to do a bit better than it does right now), so if you want your code to gracefully degrade when the DataStoreService is having issues you’ll have to write your own more complicated behavior for that.