I have problem with datastore. it doesn’t save values when player leaves. I tried to fix it but no effects.
local DataStoreService = game:GetService('DataStoreService')
local SaveValue = DataStoreService:GetDataStore('SaveValue')
game.Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local hiddenvalue = Instance.new("Folder")
hiddenvalue.Name = "hiddenfolder"
hiddenvalue.Parent = leaderstats
local cash = Instance.new("IntValue")
cash.Name = "Coins"
cash.Parent = hiddenvalue
local data
local success, errormessage = pcall(function()
data = SaveValue:GetAsync(player.UserId .. "-coins")
end)
if success then
cash.Value = data or 0 -- Default to 0 if data is nil
else
print("There was an error whilst getting your data")
warn(errormessage)
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local success, errormessage = pcall(function()
SaveValue:UpdateAsync(player.UserId .. "-coins", player.hiddenfolder.Coins.Value)
end)
if success then
print("Player Data Saved")
else
print("Player data not saved")
warn(errormessage)
end
end)
Use SetAsync() instead. Also I would suggest putting the PlayerRemoving Function into the PlayerAdded function.
Here is the script with my changes:
local DataStoreService = game:GetService('DataStoreService')
local SaveValue = DataStoreService:GetDataStore('SaveValue')
game.Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local hiddenvalue = Instance.new("Folder")
hiddenvalue.Name = "hiddenfolder"
hiddenvalue.Parent = leaderstats
local cash = Instance.new("IntValue")
cash.Name = "Coins"
cash.Parent = hiddenvalue
local data
local success, errormessage = pcall(function()
data = SaveValue:GetAsync(player.UserId .. "-coins")
end)
if success then
cash.Value = data or 0 -- Default to 0 if data is nil
else
print("There was an error whilst getting your data")
warn(errormessage)
end
game.Players.PlayerRemoving:Connect(function()
local success, errormessage = pcall(function()
SaveValue:SetAsync(player.UserId .. "-coins", player.hiddenfolder.Coins.Value)
end)
if success then
print("Player Data Saved")
else
print("Player data not saved")
warn(errormessage)
end
end)
end)
Add a game:BindToClose() function to ensure the data saves both on Studio and in game.
Like this:
local DataStoreService = game:GetService('DataStoreService')
local SaveValue = DataStoreService:GetDataStore('SaveValue')
function SaveData(player)
local success, errormessage = pcall(function()
SaveValue:SetAsync(player.UserId .. "-coins", player.hiddenfolder.Coins.Value)
end)
if success then
print("Player Data Saved")
else
print("Player data not saved")
warn(errormessage)
end
end
game.Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local hiddenvalue = Instance.new("Folder")
hiddenvalue.Name = "hiddenfolder"
hiddenvalue.Parent = leaderstats
local cash = Instance.new("IntValue")
cash.Name = "Coins"
cash.Parent = hiddenvalue
local data
local success, errormessage = pcall(function()
data = SaveValue:GetAsync(player.UserId .. "-coins")
end)
if success then
cash.Value = data or 0 -- Default to 0 if data is nil
else
print("There was an error whilst getting your data")
warn(errormessage)
end
game.Players.PlayerRemoving:Connect(SaveData)
end)
game:BindToClose(function()
for _,player in pairs(game:GetService("Players"):GetPlayers()) do
SaveData(player)
end
end)
The reason why I believe your code doesn’t work when the player leaves is that you index player.hiddenfolder, which doesn’t exist and is going to cause the script to error. Since hiddenfolder is created and parented to leaderstats the correct hierarchy should be: player.leaderstats.hiddenfolder
The suggestions posted have been helpful, but I noticed one glaring flaw with setting up your data system. If the GetAsync call fails, the player’s coin leaderstat value will be left at 0 (default value for IntValues.) Afterward, you have a PlayerRemoving listener and a suggested BindToClose handler which will save the player’s data using their coin leaderstat value (0) This will result in data loss.
Even if you correct that issue, there are still some considerations to make here. What if the server abruptly ends and PlayerRemoving and BindToClose are never called? Without periodically auto-saving you will lose player data. What if the UpdateAsync call fails when the player leaves? You simply just warn that the player data was not saved, goodbye player data!
I highly suggest you use a module like ProfileService or DataStore2 because this stuff is tricky to get right. Those two modules periodically auto-save data, implement caching, etc.
The leaderstat values should also be purely frontend and shouldn’t impact how the player’s data is saved on the server.
Give the server time to save the data with the :BindToClose function
Use :SetAsync instead of :UpdateAsync
If you still want to use UpdateAsync, your code should look something like this:
SaveValue:UpdateAsync(player.UserId .. "-coins", function(PreviousData)
if PreviousData ~= nil then
local AmountToAdd = player.hiddenfolder.Coins.Value - PreviousData
return player.hiddenfolder.Coins.Value + AmountToAdd
else
return player.hiddenfolder.Coins.Value --Runs if the player has no previous data
end
end)
@TheSoldierOfTheNoobs, putting the PlayerRemoving event in the PlayerAdded event is a bad idea because it will fire multiple times and cause other issues.