Saving many stats at once

Right, so. I wanted to add a feature to my game called tokens. When you step on a button, you get a random token. However, I want to add many tokens, with many chances. It’s not the chances that need to be saved, it’s the tokens.
There’s the problem.

These tokens will have a lot of chances, and I need to save them all. 6 different Tokens per token machine is 6 extra stats to save. Adding just 2 machines is 12. It adds up fast.

I need a way to save all those stats. Maybe I could save them as one string, or I could use a table. But I’ve heard those don’t work that well. What exactly should I do? I may rethink using a table…

1 Like

yeah, use a table i think, that would probs be the best way

i know this is ludicrous but what if i wanted to use over 100 values would it still work

1 Like

For one of my games, I have a total of 198 different stats to save in a folder structure. I created a table of all the stats, their name, their value, and their parent, then encoded the table into a JSON string. The datastore service only saves one string, but that string contains the data for an incredible amount of individual stats. For loading, I decode the JSON (Roblox has a JSON encode/decode system), then loop through the saved stats to find the objects by checking the parent value and their name. I hope this helps!

Snippets from my code:

Saving:

local statstorage = player:WaitForChild("Data"):GetDescendants()
	local dataToEncode = {}
	
	local objectID = 1
	for i, object in pairs(statstorage) do
		if object.ClassName ~= "Folder" then
			table.insert(dataToEncode, {object.Name, object.Value, object.Parent.Name})
			objectID += 1
		end
	end
	
	
	local encodedData = httpService:JSONEncode(dataToEncode)
	
	datastore:SetAsync("Data"..player.UserId, encodedData)

Loading:

local stats = player:WaitForChild("Data"):GetDescendants()
	
	local encodedData = datastore:GetAsync("Data"..player.UserId)
	local decodedData = httpService:JSONDecode(encodedData)

    --... Loop through actual objects created when a player joins, setting the values.
	for index, savedDataValue in pairs(decodedData) do
		if savedDataValue ~= nil then
            ...

Sorry for takin so long to reply. I have a question.

local dataStoreService = game:GetService("DataStoreService")
local rarityDataStore = dataStoreService:GetDataStore("Rarity")
local rpDataStore = dataStoreService:GetDataStore("RP")
local luckDataStore = dataStoreService:GetDataStore("Luck")

game.Players.PlayerAdded:Connect(function(plr)
	local playerStats = Instance.new("Folder",plr)
	playerStats.Name = "playerStats"
	playerStats.Parent = plr

	local rarity = Instance.new("NumberValue",playerStats)
	rarity.Name = "Rarity"
	rarity.Value = 0
	rarity.Parent = playerStats
	
	local rp = Instance.new("NumberValue",playerStats)
	rp.Name = "RP"
	rp.Value = 0
	rp.Parent = playerStats
	
	local luck = Instance.new("NumberValue",playerStats)
	luck.Name = "Luck"
	luck.Value = 1
	luck.Parent = playerStats

--repeat for many more stats

	local playerUserId = "player_"..plr.UserId
	
	--------------------------------------

	local rarityData
	local success, errormessage = pcall(function()
		rarityData = rarityDataStore:GetAsync(playerUserId)
	end)
	if success  then
		rarity.Value = rarityData
	end
	
	--------------------------------------
	
	local rpData
	local success, errormessage = pcall(function()
		rpData = rpDataStore:GetAsync(playerUserId)
	end)
	if success  then
		rp.Value = rpData
	end
	
	--------------------------------------

	local luckData
	local success, errormessage = pcall(function()
		luckData = luckDataStore:GetAsync(playerUserId)
	end)
	if success  then
		luck.Value = luckData
	end
end)

--Saving Data--
game.Players.PlayerRemoving:Connect(function(player)
	local playerUserId = "player_"..player.UserId
	
	--------------------------------------

	local rarityValue = player.playerStats.Rarity.Value
	
	local success, errormessage = pcall(function()
		rarityDataStore:SetAsync(playerUserId, rarityValue)
	end)
	
--repeat for many more stats
	--------------------------------------
	
	local rpValue = player.playerStats.RP.Value

	local success, errormessage = pcall(function()
		rpDataStore:SetAsync(playerUserId, rpValue)
	end)

	--------------------------------------

	local luckValue = player.playerStats.Luck.Value

	local success, errormessage = pcall(function()
		luckDataStore:SetAsync(playerUserId, luckValue)
	end)
end)

game:BindToClose(function(player)
	for _, Player in pairs(game.Players:GetPlayers()) do
		local playerUserId = "player_".. Player.UserId
		
		--------------------------------------

		local rarityValue = Player.playerStats.Rarity.Value

		local success, errormessage = pcall(function()
			rarityDataStore:SetAsync(playerUserId, rarityValue)
		end)
		
		--------------------------------------
		
		local rpValue = player.playerStats.RP.Value

		local success, errormessage = pcall(function()
			rpDataStore:SetAsync(playerUserId, rpValue)
		end)

		--------------------------------------

		local luckValue = player.playerStats.Luck.Value

		local success, errormessage = pcall(function()
			luckDataStore:SetAsync(playerUserId, luckValue)
		end)
	end
end)

Could this be optimized in any way to make it save a table of stats instead of all the individual stats?

saving and loading like this is like begging for disaster, you should instead use profileservice and you can easily load and save as many tables you want

I’m gonna be honest, the first time i saw it i was confused so bad

Yes that can and should to be optimized. Instead of using :SetAsync() for every value, loop through your values and insert them into a table, then use one :SetAsync() on the whole table for all the values.

The code I provided earlier is an example of what the saving/loading looks like, just the table isn’t really shown because it is a folder structure patented to the player rather than a bunch of values instantiated in a script.

The GetDescendants() method returns a table of all my values (as well as their parent folders, so I just sort out the folders).

In your case, you can do something like:

statTable = {
{“luck”, luck.Value},
{“RP”, rp.Value},
{”Rarity”, rarity.Value}
}

This code is an example, not to be copy/pasted. I hope this clarifies things!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.