Hello everyone, i made a save data, but when player leaves doesn’t save, here is the script:
local dataStore = game:GetService(“DataStoreService”)
local data = dataStore:GetDataStore(“Stats”)
game.Players.PlayerAdded:Connect(function(Player)
local leaderstats = Instance.new(“Folder”,Player)
leaderstats.Name = “leaderstats”
local level = Instance.new("NumberValue",leaderstats)
level.Name = "Level"
level.Value = 0
local savedLevel = data:GetAsync(Player.UserId.."-Level")
if savedLevel then
level.Value = savedLevel
end
end)
game.Players.PlayerRemoving:Connect(function(plr)
local success,err = pcall(function()
data:SetAsync(plr.UserId.."-Level")
end)
The second argument in SetAsync is missing! Using pcall is great for catching errors, but you still need to check them afterwards. Try adding this afterwards.
local success,err = pcall(function()
local level = plr:FindFirstChild("Level", true)
data:SetAsync(plr.UserId.."-Level", level.Value)
end)
if not success then -- check for failure!
warn(err) -- print the error, and continue running
end
Another issue may arise if you are testing this in studio. It is very often the case that the server shuts down before the player removing call can finish. This community tutorial covers how to solve such issues and other common ones.
You need to pass the value you want to save into the second argument of SetAsync
In your case, it might look like this:
game.Players.PlayerRemoving:Connect(function(plr)
local level = plr:FindFirstChild("leaderstats") and plr.leaderstats:FindFirstChild("Level")
if level then
data:SetAsync(plr.UserId.."-Level", level.Value)
end
end)
Something like game:bindtoclose(function()
For i, player in ipairs(game:GetService(“Players”):GetPlayers()) do
local level = player:FindFirstChild(“Level”) if level then data:SetAsync(player.UserId…"-Level", level.Value) end end
My apologies, I missed that the level stat was in the leaderstats, not directly in the player. My original reply has been edited with a corrected solution
No problem, happy to help. Next you may want to consider saving a table so that you can store more data values without needing to make additional datastore calls. Here’s one way you might do that:
game.Players.PlayerAdded:Connect(function(plr)
local save = data:GetAsync(plr.UserId.."-Data") or {}
-- it is actually better to parent after setting the name, otherwise
-- plr:WaitForChild("leaderstats") may not work correctly
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = plr
local level = Instance.new("IntValue")
level.Name = "Level"
level.Value = save.Level or 0
level.Parent = leaderstats
local money = Instance.new("NumberValue")
money.Name = "Money"
money.Value = save.Money or 10
money.Parent = leaderstats
end
game.Players.PlayerRemoving:Connect(function(plr)
local leaderstats = plr:FindFirstChild("leaderstats")
if leaderstats then
local save = {}
save.Level = leaderstats:FindFirstChild("Level") and leaderstats.Level.Value
save.Money = leaderstats:FindFirstChild("Money") and leaderstats.Money.Value
data:SetAsync(plr.UserId.."-Data", save)
end
end)
In this example I have stored level as an IntValue, so that it is always a whole number. This can help prevent floating point percision errors.
You can easily add other values to the player’s save file, including other value types such as strings or booleans, by following the same format as what is used for level and money. You should also look into auto-saving and proper error handling as others in the thread have suggested.