General datastore issues, further info in post

Hello all! haven’t posted here in a while.

I’ve been working on a game and i have recently tried to implement data saving related stuff to it, but it has resulted in all forms of horrible outcomes

Some of them go as follows

  • Data doesn’t save every time (this is why there’s a math.huge used in the sample, as a desperate fix that didn’t even fix anything)
  • Data is name based, so if i rename one of the cars it will delete all data for the previous name of the car. (switching to updateasync could work???)
  • The saving just doesn’t work right, god i beg of anyone to please help me with this

Here is a full code sample of the main data manager

local DataStoreService = game:GetService("DataStoreService")
local dataStore = DataStoreService:GetDataStore("PlayerStatsStore")

local Attempts = 1 -- Attempt Counter
local Success, Error -- do not mess with these, this is so we can access the pcall within the loop


-- GUIDE TO THE ORDER OF THE DATASTORE--
-- there is no guide

function tableFromFolder(folder: Folder) -- If you want ANY instance, replace with "Instance"
	local folderTable = {}
	-- Loop through each child
	for _, child in folder:GetChildren() do
		-- If it is a folder, use recursion to do the same and
		-- convert its children into another table and use that
		if child:IsA("Folder") then
			folderTable[child.Name] = tableFromFolder(child)
			-- If it is a value (such as StringValue or BoolValue), store its value directly
		elseif child:IsA("ValueBase") then
			folderTable[child.Name] = child.Value
		end
	end
	-- Return the finished result
	--print(folderTable)
	return folderTable
end

local function saveData(player) -- The functions that saves data
	
	local tableToSave = {}
	
	tableToSave = tableFromFolder(player.CarData)
	print(tableToSave)
	
	print("WAITED")
	
	repeat
		print("WILL DO")
		Success, Error = pcall(dataStore.SetAsync, dataStore, player.UserId, tableToSave) -- this is apparently the "better" way
		Attempts += 1 -- Adds Attempt
		print("DID")
		if not Success then task.wait(2) end -- if failed, waits to try again (firing very fast can cause a queue)
	until Success or Attempts > math.huge -- Conditions to Break upon
	
	if Success then
		print("Data has been saved!")
	else
		print("Data hasn't been saved!")
		warn(Error)		
	end
end


game.Players.PlayerRemoving:Connect(function(player) -- When a player leaves the game
	saveData(player) -- Save the data
end)


game:BindToClose(function() -- When the server shuts down
	for _, player in pairs(game.Players:GetPlayers()) do
		saveData(player) -- Save the data
	end
end)


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

	local DataFol = Instance.new("Folder")
	DataFol.Name = "CarData"
	DataFol.Parent = player
	
	local children = game.ReplicatedStorage.Cars:GetChildren()
	
	for i, child in ipairs(children) do
		if child:IsA("Model") and child:FindFirstChild("CarColor") then
			local Fol = Instance.new("Folder")
			Fol.Name = child.Name
			Fol.Parent = DataFol
			
			local Dist = Instance.new("NumberValue")
			Dist.Name = "Distance"
			Dist.Parent = Fol
			
			local ServDist = Instance.new("NumberValue")
			ServDist.Name = "ServDistance"
			ServDist.Parent = Fol
			
			local Tire = Instance.new("StringValue")
			Tire.Name = "Tire"
			Tire.Parent = Fol
		end
	end

	local data
	local success, err = pcall(function()

		data = dataStore:GetAsync(player.UserId)

	end)

	if success and data then
		
		print("DATA")
		print(data)
		
		local children = player.CarData:GetChildren()
		
		for i, child in ipairs(children) do
			if child:IsA("Folder") then
				print("found child: "..child.Name)
				local cardata = data[child.Name]
				print("CARDATA")
				print(cardata)
				
				if cardata ~= nil then
					print("found data!")
					child.Distance.Value = cardata["Distance"]
					child.ServDistance.Value = cardata["ServDistance"]
					child.Tire.Value = cardata["Tire"]
				end
			end
		end
	else
		print("The player has no data!") -- The default will be set to 0	
	end

end)

There’s a lot of prints in an attempt to check if it’s working (it isn’t, “WILL DO” is the last one that prints in 99% of cases)

Any help with this please? i don’t know what else to do at this point, datastore related things are definitely not my field, thanks in advance.

It’s pretty hard trying to force a data save when a player leaves, so you should save player data anytime you can. That’s why I recommend you to use ProfileService instead:

ProfileService:

GitHub:
https://madstudioroblox.github.io/ProfileService/

I really recommend you to use ProfileService so you don’t have any more problems with DataStore in the future, and this is not a complicated module, it’s actually a really easy module that can be learned on how to use it in max 20-30m.

How can I convert my normal datastore usage scripts to work with profile service without resetting data?