✓ Accepted answer
Before getting into the actual problem, why do you have two different scripts for creating leaderstats and loading and saving them? These all could be in one script to make things easier. Also, you shouldn't really try solving issues by adding an unnecessary wait() at the beginning -- WaitForChild exists.
Going into the actual problem now, there are a few reasons as to why your data doesn't save:
- In studio specifically, you may not have Enable Studio Access to API Services toggled on. If not, go into Home > Game Settings > Options > Enable Studio Access to API Services
- If you're the only player in the server and have left the game, the server is not given enough time to save the data and the server shuts down abruptly.
- Data stores use Web API calls, which could potentially fail at times due to internal server errors
So, how can the two issues below be solved? First, you would need to implement a BindToClose callback. Whenever the server is scheduled to shut down, BindToClose will make the server wait a maximum of 30 seconds before the server can shut down and execute all callbacks delegated to the function. This is where you can save the data for all players and the server will shut down when all of the data has been saved (or when 30 seconds has been elapsed)
As for the last issue, this can be solved by implementing a retry system that is limited to a specific amount of retries. You will have to use pcall so you save the data in protected mode where errors that occur doesn't terminate further execution of the code but indicates whether or not it ran successfully
Also, it's easier to use a dictionary to save and retrieve the data. All together, here's what the code should be:
local ds = game:GetService("DataStoreService"):GetDataStore("SaveData")
local Players = game:GetService("Players")
function SaveData(player)
local MAX_TRIES = 5
local tries = 0
local saveData = {
Money = player.leaderstats.Money.Value;
}
repeat
local success = pcall(function()
ds:SetAsync("id_"..player.UserId, saveData)
end)
wait(6)
tries += 1
until success or tries >= 5
end
function GetData(player)
local MAX_TRIES = 5
local tries = 0
local result
repeat
local success = pcall(function()
result = ds:GetAsync("id_"..player.UserId)
end)
wait(7)
tries += 1
until success or tries >= 5
return result
end
game.Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local money = Instance.new("IntValue")
money.Name = "Money"
money.Value = 0
local data = GetData(player)
if data then
money.Value = data.Money
end
end)
game.Players.PlayerRemoving:Connect(SaveData)
game:BindToClose(function()
local player_list = Players:GetPlayers()
local player_count = #player_list
local saved_players = {}
for _, player in ipairs(player_list) do
task.spawn(function()
SaveData(player)
table.insert(saved_players, player)
end)
end
while (#saved_players < player_count) do task.wait() end
end)
4 comments
Okay so i tried your script and i tested it with a mate of mine but the weird thing is all the players money seem to be client sided we both joined i had 75 he had 50 i left and rejoined now we both had 0 but on his screen it still was increasing i am very confused
I can tell that the type of script you used to increment the player's stats was a local script. Most of things done on the client will not replicate to the server in respect with the client-server model (FilteringEnabled). So it's as if the server didn't see the change in the stats. You should try using a script to increment the stats
i am using a script not a localscript
i found the issue word then somewhere was set as a comment i very smart yes