A few notes to point out in your code:
-
Don’t use the 2nd parameter of Instance.new: It leads to some performance issues as explained in this official PSA. You should set the required properties other than the parent, then set the parent last
-
I would advise against saving the data in different keys as each request contributes to the request queue and will fill up the queue quickly so you end up getting errors as you’ve reached its limits. The best feature of DataStores is that you can store (serialisable) tables and considering that the data is associated with the player as stats, you can save all of the data in a table with one key
-
Nesting functions isn’t a great idea here, since every time a player joins, a new function is created and will eventually pile up as more and more players join. There is no reason for it to be in a function, since it isn’t being reused elsewhere. You should also stop the while loop if the player has disconnected
-
You can minimize data loss by implementing a forced save if the server is awaiting shut down and by implementing an auto save feature. Forced saved at shut down helps minimize data loss tremendously as this will require using game:BindToClose, which is a function that will call the callback/binded function and will wait for it to finish executing or at the very least, wait a minimum of 30 seconds, before the server shuts down due to there being no more players remaining or the developer forced shut down the servers. Autosaving helps too and I don’t mean saving the data as it changes, because that could reach the limits quickly but it depends, I mean saving it every few minutes.
Try this one out:
local event = game.ReplicatedStorage:WaitForChild("coin")
local players = game:GetService("Players")
local datastore = game:GetService("DataStoreService")
local myData = datastore:GetDataStore("myData")
-- Saves a specific player's data
function SaveData(player)
local success, err = pcall(function()
myData:SetAsync(player.UserId.."-data", {
Coins = player.leaderstats.Coins.Value;
Gate = player.leaderstats.Gate1.Value;
})
end)
if not success then
warn(err)
end
end
players.PlayerAdded:Connect(function(plr)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = plr
local coins = Instance.new("IntValue")
coins.Name = "Coins"
coins.Parent = leaderstats
local gate1 = Instance.new("BoolValue")
gate1.Name = "Gate1"
gate1.Value = leaderstats
print("Boolean Status :",gate1.Value)
local success, res = pcall(function()
return myData:GetAsync(plr.UserId .. "-data")
end)
if success then
coins.Value = res.Coins
gate1.Value = res.Gate
else
warn(res)
end
while wait(25) do
-- Terminate loop if the player disconnects
if (not plr) then break end
event:FireClient(plr)
coins.Value += math.random(1,100)
end
end)
players.PlayerRemoving:Connect(function(plr)
SaveData(plr)
end)
-- Save all players' data when the server is supposed to shut down
game:BindToClose(function()
for _, player in players:GetPlayers() do
SaveData(player)
end
end)