Can Datas Only In Leaderstats Be Saved?

I have some IntValues in my game that aren’t in the leaderstats folder, they’re in a folder called HiddenVals, because they are hidden. One of them is “ClickGain” which is how many currency you gain per click, however this IntValue needs to save so when players leave and rejoin it stays the same. I am trying to use my datastore script to save this data (which does work, I’ve used it before on values in the leaderstats folder), but it doesn’t save for some reason. Here is my data store script

	local DSS = game:GetService("DataStoreService")
	local DataStore = DSS:GetDataStore("Data")
	
	local coin
	local cals
	local cg
	local success, errormessage = pcall(function()
		coin = DataStore:GetAsync(Player.UserId.."-Coins")
		cals = DataStore:GetAsync(Player.UserId.."-Calories")
		cg = DataStore:GetAsync(Player.UserId.."-ClickGain")
	end)
	
	if success then 
		Coins.Value = coin
		Calories.Value = cals
		ClickGain.Value = cg
	else
		print("There was an error while saving")
		warn(errormessage)		
	end
end)
	
game.Players.PlayerRemoving:Connect(function(player)
	local DSS = game:GetService("DataStoreService")
	local DataStore = DSS:GetDataStore("Data")
	local success, errormessage = pcall(function()
		DataStore:SetAsync(player.UserId.."-Coins",player.leaderstats.Coins.Value)
		DataStore:SetAsync(player.UserId.."-Calories",player.leaderstats.Calories.Value)
		DataStore:SetAsync(player.UserId.."-ClickGain",player.HiddenVals.ClickGain.Value)
	end)
	
	if success then
		print("Player Data saved successfully")
	else
		print("error when saving data")
		warn(errormessage)
	end
	end)

There’s probably some obvious answer that I don’t see, and I am sorry if that is the case.

2 Likes

Does it error at all?
If so, could you share the output message?

There are better ways to do this since you could use one datastore for all of these values or you could use Datastore2 as a way of saving your data. It’s also better to have your variables on the outside of your functions, for example, put the datastore variables at the top of your code and only use: GetDataStore() once instead of every time a play joins and leaves.

A better way you could save it is by using a table to save values in a certain order so it can be loaded and called in that specific order.

Saving:

local DataToSave = {
   Player.leaderstats.Coins.Value, -- Coins value
   Player.leaderstats.Calories.Value, -- Calories value
   Player.HiddenVals.ClickGain.Value, -- Clickgain value
}

local succ,err = pcall(function()
 DataStore:SetAsync(Player.UserId .. "-key", DataToSave)
end)

if not succ then
  warn(err)
end

Loading:

local DataLoaded = DataStore:GetAsync(Player.UserId .. "-key")

if DataLoaded then
 Instance.Value = DataLoaded[1] -- Coins
 Instance.Value = DataLoaded[2] -- Calories
 Instance.Value = DataLoaded[3] -- Clickgain
end
1 Like

Doesn’t matter where data is. If it’s passed to a DataStore write method (Set, Update & Increment), then it’ll be written to the DataStore. What you are most likely experiencing is a code error which comes from the lack of debugging on your end, or if that was done then it’s not clearly indicated.

Details will need to be provided to further help you with your issue. Remember that saying that your code work isn’t sufficient enough to know the problem: we can’t assume we know what you mean by it’s not working. Be sure to do some debugging yourself as well.

With that aside, I did notice an awful thing about your DataStore: you are making far too many calls because you aren’t using DataStores efficiently. You end up using three keys in a DataStore to save three different values when you can instead pack that away into a dictionary.

Nope, no errors, if just doesn’t save

This is way more efficient way of saving data, than having multiple keys, and datastores

I doubt that. I can guarantee it will fail if what you’ve posted is the full script (and if it isn’t, perhaps post the full script) because you’re indexing variables that don’t exist, namely Coins, Calories and ClickGain on lines 14, 15, 16.

Can you confirm that a) it doesn’t error at all, and that you’ve just not provided the whole script, and b) that it prints “Player Data saved successfully” after attempting to save?

It does print player data saved successfully and it doesn’t error. This is not the entire script.

Well given that the loading part of the script relies on variables that you haven’t defined in the part that you’ve chosen to give us, I recommend you provide the whole data saving and loading script.

If it prints that it saved, then it has saved, so its likely that your values are wrong, the key you’re loading from isn’t that same as the key you’re saving to, or you’re reading from a different valueobject when saving than you’re setting to when loading. All of those would only be identifiable with the part of the script you’ve decided to omit.

Here is the whole script;

 game.Players.PlayerAdded:Connect(function(Player)
    	local LFolder = Instance.new("Folder")
    	LFolder.Name = "leaderstats"
    	LFolder.Parent = Player
	
	local Folder = Instance.new("Folder")
	Folder.Name = "HiddenVals"
	Folder.Parent = Player
	
	
	local Calories = Instance.new("IntValue")
	Calories.Name = "Calories"
	Calories.Parent = LFolder
	
	local Coins = Instance.new("IntValue")
	Coins.Name = "Coins"
	Coins.Parent = LFolder
	
	local ClickGain = Instance.new("IntValue")
	ClickGain.Name = "ClickGain"
	ClickGain.Parent = Folder
	ClickGain.Value = 1

local DSS = game:GetService("DataStoreService")
	local DataStore = DSS:GetDataStore("Data")
	
	local coin
	local cals
	local cg
	local success, errormessage = pcall(function()
		coin = DataStore:GetAsync(Player.UserId.."-Coins")
		cals = DataStore:GetAsync(Player.UserId.."-Calories")
		cg = DataStore:GetAsync(Player.UserId.."-ClickGain")
	end)
	
	if success then 
		Coins.Value = coin
		Calories.Value = cals
		ClickGain.Value = cg
	else
		print("There was an error while saving")
		warn(errormessage)		
	end
end)
	
game.Players.PlayerRemoving:Connect(function(player)
	local DSS = game:GetService("DataStoreService")
	local DataStore = DSS:GetDataStore("Data")
	local success, errormessage = pcall(function()
		DataStore:SetAsync(player.UserId.."-Coins",player.leaderstats.Coins.Value)
		DataStore:SetAsync(player.UserId.."-Calories",player.leaderstats.Calories.Value)
		DataStore:SetAsync(player.UserId.."-ClickGain",player.HiddenVals.ClickGain.Value)
	end)
	
	if success then
		print("Player Data saved successfully")
	else
		print("error when saving data")
		warn(errormessage)
	end
	end)

Okay so I noticed a couple of things:

  1. The clickgain value immediately gets set to 0 when a new player joins the game, because you load cg from the datastore, the key doesn’t exist, so the value is nil, and setting an IntValue to nil will resolve to a value of 0. Is this intentional? The only reason I ask is that you deliberately set it to 1 just to get overrided to 0 or another value from the datastore.

  2. I put this in a blank baseplate game, joined, left, it correctly saved my data as being 0 upon leaving the first time, and loaded this in instead of nil next time. I then used the command line to set the IntValue’s value to 2000, left, it saved, came back, it loaded and correctly set it to 2000. Your code therefore seems to do exactly what you asked it to. Any problems (other than that pointed out in 1.) are somewhere else in your programming, not in this saving/loading script.

Alright, I’ll dig through all my scripts and try to find a problem. I am not getting any errors at all in output

What is it that is making you believe it isn’t saving? That might help to narrow down the issue. Look into your scripts that use/display the value of ClickGain to ensure it’s not those that are having the issue and are either reading the wrong ValueObject or something.

It’s also not particularly recommended to store things other than leaderstats in the Player object so try using a player-named folder in ReplicatedStorage that you create when they join and destroy after saving to see if that solves your issues.

Hm… maybe. Also how do I prevent the clickgain value from being set to nil when a player joins?

ClickGain.Value = cg or yourDefaultValue

or if you’ve already set it to the default earlier on in the code (like in your script), you can do:

ClickGain.Value = cg or ClickGain.Value

which will only update the value if cg is not nil. If it is nil, it’ll keep the value ClickGain has already.