Is this a good script for saving/loading player data? (+What is DataStore2? And is it needed at all?)

I read a lot about saving data, and more than once I came across topics where people said that in their games there were problems, in the form of loss of data players.

Maybe the topics have become outdated, and maybe it used to be a lot of problems with the Data Store, but now it’s better, I don’t know.

After that I found a lot of posts and topics about DataStore2, but I could never figure out what it was, because I could not find the explanation I needed.

DataStore2 – This is the same Data Store from roblox, just any saved data is accompanied by a bunch of “If” and “while”/“repeat”/“for”?
Or is DataStore2, something else?

And do I, for example, need it? Here’s my save/load script.

Compressed script(The most important thing)

local ServerOFF = false

local ClearTable = function() -- Table with the original values of everything.
	local Table = { ... }
	return Table
end


game.Players.PlayerAdded:Connect(function(plr)
	-- some script...
	local Table = ClearTable()
	
	local Status = Instance.new("Folder")
	Status.Name = "Value"
	Status.Parent = plr

	local LoadSuccess = Instance.new("BoolValue") -- true = player data was successfully uploaded
	LoadSuccess.Name = "LoadSuccess"
	LoadSuccess.Parent = Status

	local SaveSuccess = Instance.new("BoolValue") --  true = player data was successfully saved
	SaveSuccess.Name = "SaveSuccess"
	SaveSuccess.Parent = Status
	
	-- x - number of attempts, Save - table with saved data, success - success of data loading
	local x, Save, success = 0, nil, false
	while not success and x < 3 do
		if x>0 then task.wait(0.5) end
		x += 1
		success,Save = pcall(function()
			return SaveData:GetAsync(plr.UserId)
		end)
	end
	-- If the data could not be loaded in 3 attempts, a window will appear with a button that, when clicked, will retry.
	if not success then
		-- some script...
		while not success and plr.Parent do
			Button.MouseButton1Click:Wait()
			success,Save = pcall(function()
				return SaveData:GetAsync(plr.UserId)
			end)
			if not success then
				Button.Text = "Error"
				task.wait(0.6)
				Button.Text = "try again"
			end
		end
		Button.Text = "Success"
	end

	-- If there is a save, apply all data from the save.
	-- Otherwise, create a save for a new player, and display a special window.
	if Save then
		-- some script...
	else
		SaveData:SetAsync(plr.UserId,Table)
		SaveCoins:SetAsync(plr.UserId,0)
		SaveSurvivals:SetAsync(plr.UserId,0)
		-- some script...
	end
	-- some script...
	if not plr.Parent then return end -- Check if the player has left the game during this time.
	LoadSuccess.Value = success
	-- some script...
end)

function FunctionSaveData(plr)
	if not plr:FindFirstChild("Value") then return end				-- Checking if a player has a main folder
	if not plr.Value:FindFirstChild("LoadSuccess") then return end	-- Check if there is a value with success of loading
	local LoadSuccess = plr.Value.LoadSuccess.Value
	if not LoadSuccess then return end -- Checking if the player is loaded
	-- some script...
	local Table = ClearTable()
	
	if ServerOFF then x = -999 end -- If the server is down, then try to save the data all possible time
	
	while (not sucData or not sucCoins or sucSurvivals) and x < 4 do
		x += 1
		if not sucData then -- If no data has been saved, save
			sucData,errData = pcall(function()
				SaveData:UpdateAsync(plr.UserId,function(old)
					-- some script...
					return Table
				end)
			end)
		end

		if not sucCoins then -- If the number of coins has not been saved, save
			sucCoins,errCoins = pcall(function()
				SaveCoins:UpdateAsync(plr.UserId,function(old) return ...Value end)
			end)
		end

		if not sucSurvivals then -- If the number of survivals has not been saved, save
			sucSurvivals,errSurvivals = pcall(function()
				SaveSurvivals:UpdateAsync(plr.UserId,function(old) return ...Value end)
			end)
		end

		-- If something is not saved, print an error. (For studio tests only)
		if not sucData or not sucCoins or not sucSurvivals then
			print(errData,"|",errCoins,"|",errSurvivals)
			print("problems with saves")
		end

	end

	plr.Value.SaveSuccess.Value = true

end

game.Players.PlayerRemoving:Connect(function(plr)
	FunctionSaveData(plr)
end)


game:BindToClose(function()
	ServerOFF = true
	print("SERVER IS OFF")
	local Players = game:GetService("Players"):GetChildren()
	if #Players == 0 then return end
	local success = false

	-- Does not allow the server to close until the data is not saved by all players.
	-- MAXIMUM SERVER SHUTDOWN TIME = 30 SECONDS

	while not success do
		task.wait(2)
		for _, plr in Players do
			if plr:FindFirstChild("Value") then
				if plr.Value:FindFirstChild("LoadSuccess") then
					if plr.Value.LoadSuccess.Value then
						if not plr.Value.SaveSuccess.Value then success = false break end
					end
				end
			end
			success = true
		end
		if not success then print("(SERVER OFF) - Some of the players have not saved their data, a recheck will be run") end
	end
end)

I’m wondering, is there any chance of losing data in my script? I did my best to save the data, but is there any chance that even after 3 attempts to save the data, it won’t save? If so, why would that happen, and in fact, how do I make sure the data is 100% saved?

I’ve run the game very many times in the studio, and I’ve never seen data not saved/loaded on the first attempt, so here’s a question, what has to happen for there to be an error? Are errors even possible today?

Anyway, I’m wondering if my script is perfect, or is there a chance of not saving data?

I see a bunch of reviews that DataStore2 is a very cool thing, and there will be no data loss with it.
But I don’t want to use something in my game that I don’t understand. And what I may not even need.

1 Like

If you are trying to avoid data loss entirely I would recommend using ProfileService as you shouldn’t have any problems with it.

1 Like