I’m very concerned about my data request limit, I don’t want to be messing with players data once my game is released. I’m not sure how I would increase my data requests as I’m relatively new to using data stores, got any advice?
Data
local DS = game:GetService("DataStoreService"):GetDataStore("TestData23")
local DataTable = {}
game.Players.PlayerAdded:Connect(function(Plr)
-- // Load Data.
local Key = "Key" .. Plr.UserId
local Data = DS:GetAsync(Key) or {
-- // Radio stuff
EquippedRadio = {EquippedName = "Default", Info = Items.Radios["Default"]},
Radios = {
["Default"] = {Info = Items.Radios["Default"]},
},
-- // Trail stuff
Trails = {
["None"] = {Info = Items.Trails["None"]}
},
EquippedTrail = {EquippedName = "None", Info = Items.Trails["None"]},
-- // Pet stuff
Pets = {
["None"] = {Info = Items.Pets["None"]},
},
EquippedPet = {EquippedName = "None", Info = Items.Pets["None"]},
-- // Item stuff
Inventory = {
["Default"] = {Info = Items.Tables["Default"]},
},
Equipped = {Info = Items.Tables["Default"], EquippedName = "Default"},
-- // Currency stuff
Cash = 125,
Gems = 0,
}
DataTable[Plr] = Data
-- // Data
game:GetService("ReplicatedStorage").Events.GetData:FireClient(Plr, DataTable[Plr])
-- // Other.
local AFK = Instance.new("BoolValue", Plr)
AFK.Name = "AFK"
AFK.Value = false
local Ready = Instance.new("BoolValue", Plr)
Ready.Name = "Ready"
local Intro = Instance.new("BoolValue", Plr)
Intro.Name = "Intro"
Intro.Value = true
local Kills = Instance.new("IntValue", Plr)
Kills.Name = "Kills"
local Alive = Instance.new("BoolValue", Plr)
Alive.Name = "Alive"
game:GetService("ReplicatedStorage").Events.UpdateCash:FireClient(Plr, DataTable[Plr])
end)
-- // Save Data.
game.Players.PlayerRemoving:Connect(function(Plr)
local Key = "Key" .. Plr.UserId
local Data = DataTable[Plr]
DS:SetAsync(Key, Data)
end)
Wrap your :GetAsync() and :SetAsync() in pcall functions, and repeat them every 6 seconds whenever the pcall fails. There will be cases when either function fails, so if you don’t cover all of your bases, you risk losing player data.
In your case, if the GetAsync fails and then a player decides to leave (after seeing that none of their stats loaded), your script will save a nil value to their file. Quick, easy way to wipe all of their progress. Before you start saving data, set something up to ensure that data successfully loaded first. My own game only runs save loops after data has been loaded, and I haven’t had a data loss report in a very long time.
You also want to set up frequent auto-saving. Popular games generally save data every 60 seconds. This is enough time to make sure that datastore requests don’t run out. This also means that if data fails to save, very little progress would be lost (in the case of a server shutdown). If you just rely on saving when the player leaves, you will get complaints of lost data, and they will get exponentially more frequent as the game gets more popular.
I imagine there’s more things I didn’t cover that others may want to chip in.
local Key = "Key" .. Plr.UserId
local Data = DS:GetAsync(Key)
Looks completely fine, but there’s the issue where GetAsync can fail. If it fails, you’re left with a nil value for that player in your DataTable, which gets saved when they leave.
To prevent GetAsync from failing, you can do something like this:
local Key = "Key" .. Plr.UserId
local Data
local Success, Error
repeat
Success,Error = pcall(function()
Data = DS:GetAsync(Key)
end)
if not Success then
print("An issue occurred when loading "..Plr.Name.."'s Data: "..Error)
wait(1)
end
until Success or not Plr or not Plr.Parent
if Plr and Plr.Parent then
if not Data then
-- Create a new save file
end
-- Do stuff with Data now that you're confident it's loaded
-- Set up a 60-second autosave loop using spawn() or coroutines
end
This will ensure that your data properly loads. It will also stop running if the Player leaves during the loading sequence.
Next, you’ll want to fix your method of saving. Put something like this before you save data:
if DataTable[plr.Name] then
-- Saving stuff
end
Basically, don’t save the data if the data doesn’t even exist. Your current setup does not account for that.