Simple Leaderstats not being saved properly

I know this issue is pretty basic but I haven’t gotten to work correctly for a while now. The issue seems to be with the playerremoving function. When the player leaves, it prints “player left” but not “player gone” or “player gone2”. So for some reason, the functions aren’t running properly and aren’t reaching the end. Anyone got a clue or see something I don’t?

local DataStoreService = game:GetService("DataStoreService")
local cashSave = DataStoreService:GetDataStore("CashStorage")
local daySave = DataStoreService:GetDataStore("DayStorage")
local day = game.Players.PlayerAdded


game.Players.PlayerAdded:Connect(function(player)

	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local day = Instance.new("IntValue")
	day.Name = "Day"
	day.Value = "0"
	day.Parent = leaderstats
	
	local cash = Instance.new("IntValue")
	cash.Name = "Cash"
	cash.Value = "0"
	cash.Parent = leaderstats
	
--Ingredient stats
	
	local ingredients = Instance.new("Folder")
	ingredients.Name = "Ingredients"
	ingredients.Parent = player
	
	local pineapple = Instance.new("BoolValue")
	pineapple.Name = "Pineapple"
	pineapple.Parent = ingredients
	
	local olive = Instance.new("BoolValue")
	olive.Name = "Olive"
	olive.Parent = ingredients
	
	local mushroom = Instance.new("BoolValue")
	mushroom.Name = "Mushroom"
	mushroom.Parent = ingredients
	
	local spinach = Instance.new("BoolValue")
	spinach.Name = "Spinach"
	spinach.Parent = ingredients
	
	local bananapepper = Instance.new("BoolValue")
	bananapepper.Name = "Banana Pepper"
	bananapepper.Parent = ingredients
	
	local ham = Instance.new("BoolValue")
	ham.Name = "Ham"
	ham.Parent = ingredients
	
	local chicken = Instance.new("BoolValue")
	chicken.Name = "Chicken"
	chicken.Parent = ingredients
	
	local bacon = Instance.new("BoolValue")
	bacon.Name = "Bacon"
	bacon.Parent = ingredients		
	
	
--cash load when join
	local data
	local success, errormessage = pcall(function()
		data = cashSave:GetAsync(player.UserId.."-cash")
	end)
		
	if success then
		cash.Value = data
	else
		print("Error getting Cash Data")
		warn(errormessage)
	end
--day load when join
	local data2 
	local success, errormessage = pcall(function()
		data2 = daySave:GetAsync(player.UserId.."-day")
	end)
	
	if success then
		day.Value = data2
	else
		print("Error getting Day Data")
		warn(errormessage)
	end
	print("Joined Finished")
end)
	


game.Players.PlayerRemoving:Connect(function(player)
	print("player left")
--cash save when leave
	local success, errormessage = pcall(function()
		cashSave:SetAsync(player.UserId.."-cash",player.leaderstats.Cash.Value)
	end)
	
	if success then
		print("Cash Data saved")
	else
		print("Cash Data not saved")
		warn(errormessage)
	end
	print("player gone")
--day save when leave
	local success, errormessage = pcall(function()
		daySave:SetAsync(player.UserId.."-day",player.leaderstats.Day.Value)
	end)
	
	if success then
		print("Day Data Saved")
	else
		print("Day Data not saved")
		warn(errormessage)
	end
	print("player gone2")
end)

I used to have this problem actually, all I did to fix it was store everything in separate data stores, in different scripts. That might be a lot for you since you have all of these ingredients but I say you should only do that as a last resort because you have a lot of things to save.

If I just made individual scripts would that drastically cause higher loading times for the beginning of the game?

Yeah probably. That’s why i don’t recommend that and you should use it if you find literally nothing that helps you. Sorry I know it’s not much help. :frowning:

Thats all good. I was thinking of just saving each value once it gets changed. Would it be an issue if I saved everyone’s stats that way instead of saving on exit?

By default, you are rate-limited from writing to the same key more than once every 6 seconds. I would highly recommend using a system like DataStore2 which caches/“stores” all the data and saves it either on a set interval (~4 lines of scripting on your own) or when the player leaves.

I would argue that the best way to handle systems like this is to have the player data be in one table instead of spread out across so many stores.

When you say that I am limited to writing to the same key, does that mean I am limited in updating the same data value every 6 seconds or just overall I can only save one thing every 6 seconds?

I may be wrong, but when you do

someDataStore:SetAsync(key, value)

that counts as one “write”. If you attempt to use SetAsync/UpdateAsync again within 6 seconds, you might be rate limited.

You can save and load data in tables, don’t use a separate key for each one:

local Key = player.UserId
local DataTable = {
    Kills = leaderstats.Kills.Value,
    Coins = leaderstats.Coins.Value,
   --  etc.
}

MyDataStore:SetAsync(Key, DataTable

And then you can load data like this:

local Key = player.UserId
local Success, Data = pcall(function()
    return MyDataStore:GetAsync(Key)
end

if Success then
    if Data then
        Kills.Value = Data["Kills"]
        Coins.Value = Data["Coins"]
        -- etc.
    end
end

That is really, really discouraged, because it will not work very well. It can work, but it will not work very well(you would have to wait to call datastore again).

Having a lot of scripts don’t really slow down load times, it really depends on what is running in those scripts.

Using DataStore2 doesn’t mean data is saved better, it’s just a module to make saving easier. It’s basically normal datastores but simplified.

This helps a lot thank you! I just have one more question. How would I use a if then statement with this saving method.

For example, I want to check if certain values ==1 and if they do I want to run a function.
If I use this method of saving will I still be able to check the values when the player first joins?

Yes, you could:

if Data["Kills"] == 1 then
    -- do something
end