local DataStoreS = game:GetService(“DataStoreService”)
local PlayerDataS = DataStoreS:GetDataStore(“PlayerData”)
game.Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local Coins = Instance.new("IntValue")
Coins.Name = "Coins"
Coins.Value = 0
Coins.Parent = leaderstats
local plrData
local succes,errormsg = pcall(function()
local playerId = player.UserId
plrData = PlayerDataS:GetAsync(playerId)
end)
if succes then
if plrData then
Coins.Value = plrData[1]
end
else
warn(errormsg)
end
end)
local function savedata(player)
local leaderstats = player.leaderstats
local playerData = {leaderstats.Coins.Value}
local success, errormsg = pcall(function()
PlayerDataS:SetAsync(player.UserId,playerData)
end)
if not success then
warn(errormsg)
end
The implementation that you have here does have failsafe measures, but only for Roblox events. You do not have any sanitization done with your functions to prevent multiple unnecessary calls, such as seen with savedata. You are calling savedata for every player when the game is getting ready to close, but also calling the function when PlayerRemoving fires. I recommend creating a buffer that stores player objects as the data is saving, then removing the player object from the buffer when the data is finished saving. This might not catch every case where PlayerRemoving and BindToClose fire decently far apart, but it will prevent possible data overwriting scenarios. You could also create a data saving queue system so if you really want to have data save as the function is called, you enter it into the queue and some external thread reads from that queue list and only takes the most recent index, and discarding all the others. If you have, or plan to make, an incremental datastore system, you will have to take from the queue list and combine all of the changes, then save the data all in one SetAsync call. I recommend for those types of systems, you use UpdateAsync instead to prevent data loss.
Now, to fix your issue, it appears you didn’t provide what exactly wasn’t working. Without this crucial information, there isn’t much I can do.
However, it seems you are using an array to save player data. I recommend using a dictionary. So instead of having to do data[1] to access the player’s coins, you do data.Coins, and so on.