My stats aren't saving sometimes

At times my data works perfectly fine. But sometimes when I’m in play test it will reset my stats. Sometimes It will do this for the actual game too.

Here’s my saving part of the script:

-- Saving function
function Save_Data(Player)
	local succ, fail = pcall(function()
		local Player_Data = {}
		if game.ServerStorage.playerinfo[Player.UserId] then
			for _,ValueObj in pairs(game.ServerStorage.playerinfo[Player.UserId]:GetChildren()) do
				if not Blacklisted_Values[ValueObj.Name] then
					Player_Data[ValueObj.Name] = ValueObj.Value
				end
			end
		end
		if Player:FindFirstChild("leaderstats") then
			Stat_Data:SetAsync(Player.UserId .. "-leaderstats", Player.leaderstats.Grade.Value)
		end
		Stat_Data:SetAsync(Player.UserId, Player_Data)
	end)
	if fail then
		print(fail)
	end
end

game.Players.PlayerRemoving:Connect(function(Player)
	Save_Data(Player)
	if game.ServerStorage.playerinfo:FindFirstChild(Player.UserId) then
		game.ServerStorage.playerinfo[Player.UserId]:Destroy()
	end
end)

-- Auto Saving
while task.wait(60*#game.Players:GetPlayers()) do
	local succ, fail = pcall(function()
		for _,Player in pairs(game.Players:GetPlayers()) do
			Save_Data(Player)
			task.wait(1)
		end
	end)
	if fail then
		print(fail)
	end
end
1 Like

Anyone know why this isn’t saving correctly?

Maybe try placing more prints within the actual saving function? Sometimes you may be saving too often which would make the saving process stop and not actually save the data. You have auto-saving too, maybe there is a chance that the saving tried to occur at the same time the auto-save tried to occur?

You also said that it resets your stats, maybe the system where it loads the data to the player fails sometimes?

Also if your the only player in the server, then when you leave, the saving function won’t have enough time to save before the server shuts down. You might want to include a BindToClose saving function in there too.

1 Like

@chubbypig332211 suggested saving in a BindToClose function, however sometimes you get a timeout for saving too quickly because both saves will run twice, so I do not recommend this. Instead, create an empty table, add a player into the table when you start saving, and remove the player after the data has saved. Then, in the game:BindToClose function, wait until the number of objects in the table is <= 0. In my experience this works the best.

What’s the purpose of creating the table to check if nothing’s in it? If the script waits until there’s no more players saving what about the remaining players that are supposed to be saved? Wouldn’t they no longer exist in the game by then?

Are you getting any errors or warnings from the script? I would guess there isn’t but I’m just making sure.

No, I haven’t been able to identify any errors. Perhaps I could use analytics to view if there are any errors that occur when I leave the game?

Analytics? Do you mean the output? And if you do mean that then yeah you should. You should try having 2 players in a local server. Make one leave and see if it saves (I’d recommend a print somewhere where it successfully saves) and then make the last player leave and see if the data is successfully saved. If they are being saved, try testing your loading data function to see if it’s working properly using prints.

Alright I’ll let you know if it ends up printing any errors after the bindtoclose function.

1 Like

You dont need to autosave if you are going to save the stats on removal.
If it sometimes doesn’t save its because you have no BindToClose function.

Fix:

-- Saving function
function Save_Data(Player)
	local succ, fail = pcall(function()
		local Player_Data = {}
		if game.ServerStorage.playerinfo[Player.UserId] then
			for _,ValueObj in pairs(game.ServerStorage.playerinfo[Player.UserId]:GetChildren()) do
				if not Blacklisted_Values[ValueObj.Name] then
					Player_Data[ValueObj.Name] = ValueObj.Value
				end
			end
		end
		if Player:FindFirstChild("leaderstats") then
			Stat_Data:SetAsync(Player.UserId .. "-leaderstats", Player.leaderstats.Grade.Value)
		end
		Stat_Data:SetAsync(Player.UserId, Player_Data)
	end)
	if fail then
		print(fail)
	end
end

game.Players.PlayerRemoving:Connect(function(Player)
	Save_Data(Player)
	if game.ServerStorage.playerinfo:FindFirstChild(Player.UserId) then
		game.ServerStorage.playerinfo[Player.UserId]:Destroy()
	end
end)

game:BindToClose(function()
	wait(3)
end)

This has never happened to me before, so I’m pretty sure this is fixed.