Save data reset. How to stop this from happening?

  1. What do you want to achieve? Save data reset. How to stop this from happening?

  2. What is the issue? I get complaints on my Roblox page from players who have all their save data wiped. Normally everything works great. All my tests have never been able to replicate the problem. However, I get daily new complaints of players loosing all data.

  3. What solutions have you tried so far? I have been working tirelessly to solve this. The tricky part is checking if the player is NEW with no data vs. a player who did not load data correctly and therefore has no data. So, before I load data or set new values for a new player, I quintuple check (5 times) in .5 second intervals, to make sure there is no data (lines 209-218.) I also switched to using UpdateAsync from GetAsync (lines 206, 213 for load, and line 55 for save). Before I save, I check one of the values that should not be nil, just to make sure there really is some data (line 48). Additionally at the few key moments in the game (buy item, get item) I have a bindable event trigger the save data function. Finally, on player exit, I quintuple check (5 times) that the save data worked. (lines 599-605)

Before, people would also complain about loosing just some data – as if the data would revert to a previous save. However, after I switched to update async, the “some data” / previous save, players have stopped. However I still have players complaining about loosing all data.
I’m including my entire save/load script. The most important parts are (Make the table, lines 21-36) (Save data, lines 39-66) and (Check if new player, lines 199 – 226). The other parts of the script relate to equipping items, checking game pass, counting dragons and dragon types, and sending data to the leaderboard.

-------------------SAVE and LOAD DATA script----------------------
print("<<LOAD DATA STARTED>>")

local DataStoreService = game:GetService('DataStoreService')
local playerData = DataStoreService:GetDataStore('PlayerData')
local MarketplaceService = game:GetService("MarketplaceService")


local SaveAttempts = 5
local AutosaveInterval = 120


--------------------<<GAME PASS IDS>>-------------------------
local UnlimitedLivesID = 22712458


------------Panchos Leaderboard------------------------
local dataStore = DataStoreService:GetOrderedDataStore("Wins")
--------------------------------------------------------

---------------------------------------------------------------------------
----------------------------MAKE THE TABLE-----------------------------------
---------------------------------------------------------------------------


local function create_table(player)
	local player_stats = {}
	for _, stat in pairs(player.saveData:GetChildren()) do
		player_stats[stat.Name] = stat.Value
	end

	print("<<TABLE MADE>>")

	return player_stats

end


-------------------------------------------------------------------
--------------------SAVE DATA--------------------------------------
-------------------------------------------------------------------


local function SaveData(player) 
	local player_stats = create_table(player) --call MAKE THE TABLE
	local success, err = pcall(function()
		-- only in Baby Dragon Hot springs
		if not player.saveData.TotalDragons.Value then
			warn("<<Player's data is missing>>")
			return -- don't save if data is missing
		end

		local playerUserId = 'Player_'..player.UserId
		--playerData:SetAsync(playerUserId, player_stats)
		playerData:UpdateAsync(playerUserId, function(OldData)
			
			return player_stats
		end)
		print("*****************************************************************************")
		print("********************<<Saved data for " ..player.Name.. ".>>******************")
		print("*****************************************************************************")
		print(player_stats)
		
	end)
	return success, err
end


-------------------------------------------------------------------
--------------------PLAYER JOINS - LOAD DATA-----------------------
-------------------------------------------------------------------

local function onPlayerJoin(player)

	local saveData = Instance.new('Folder') 	--make the folder
	saveData.Name = 'saveData' 					--NAME the folder
	saveData.Parent = player					--parent the folder
	
	print("<<saveData FOLDER MADE>>")
	
	----------------------------------------------------------------------
	--------------------Make the Values for SaveData----------------------
	----------------------------------------------------------------------
	--Dragons

	local dragonWhiteAmount = Instance.new('IntValue')	--WHITE
	dragonWhiteAmount.Name = 'DragonWhiteAmount'
	dragonWhiteAmount.Parent = saveData

	local dragonPinkAmount = Instance.new('IntValue')	--Pink
	dragonPinkAmount.Name = 'DragonPinkAmount'
	dragonPinkAmount.Parent = saveData

	local dragonBlackAmount = Instance.new('IntValue')	--BLACK
	dragonBlackAmount.Name = 'DragonBlackAmount'
	dragonBlackAmount.Parent = saveData

	local dragonBlueAmount = Instance.new('IntValue')	--Blue
	dragonBlueAmount.Name = 'DragonBlueAmount'
	dragonBlueAmount.Parent = saveData

	local dragonRedAmount = Instance.new('IntValue')	--Red
	dragonRedAmount.Name = 'DragonRedAmount'
	dragonRedAmount.Parent = saveData

	local dragonYellowAmount = Instance.new('IntValue')	--Yellow
	dragonYellowAmount.Name = 'DragonYellowAmount'
	dragonYellowAmount.Parent = saveData

	local dragonGreenAmount = Instance.new('IntValue')	--Green
	dragonGreenAmount.Name = 'DragonGreenAmount'
	dragonGreenAmount.Parent = saveData

	local dragonOrangeAmount = Instance.new('IntValue')	--Orange
	dragonOrangeAmount.Name = 'DragonOrangeAmount'
	dragonOrangeAmount.Parent = saveData

	local dragonPurpleAmount = Instance.new('IntValue')	--Purple
	dragonPurpleAmount.Name = 'DragonPurpleAmount'
	dragonPurpleAmount.Parent = saveData

	--Wings

	local whiteWings = Instance.new('IntValue') --0 none, 1 have them
	whiteWings.Name = 'WhiteWings'
	whiteWings.Parent = saveData

	local blueWings = Instance.new('IntValue') --0 none, 1 have them
	blueWings.Name = 'BlueWings'
	blueWings.Parent = saveData

	local redWings = Instance.new('IntValue') --0 none, 1 have them
	redWings.Name = 'RedWings'
	redWings.Parent = saveData

	local greenWings = Instance.new('IntValue') --0 none, 1 have them
	greenWings.Name = 'GreenWings'
	greenWings.Parent = saveData

	local yellowWings = Instance.new('IntValue') --0 none, 1 have them
	yellowWings.Name = 'YellowWings'
	yellowWings.Parent = saveData

	local pinkWings = Instance.new('IntValue') --0 none, 1 have them
	pinkWings.Name = 'PinkWings'
	pinkWings.Parent = saveData

	local blackWings = Instance.new('IntValue') --0 none, 1 have them
	blackWings.Name = 'BlackWings'
	blackWings.Parent = saveData

	local rainbowWings = Instance.new('IntValue') --0 none, 1 have them
	rainbowWings.Name = 'RainbowWings'
	rainbowWings.Parent = saveData

	--Other	

	local robuxSpent = Instance.new('IntValue') --This is how much Robux the player spent, not really used for anything.
	robuxSpent.Name = 'RobuxSpent'
	robuxSpent.Parent = saveData

	local petEquip = Instance.new('IntValue')	--This remembers what baby dragon you had flying with you last.
	petEquip.Name = 'PetEquip'
	petEquip.Parent = saveData
	-- 1=White, 2=Pink, 3=Black, 4=Blue, 5=Red, 6=Green, 7=Orange, 8=Purple, 9=Orange

	local wingEquip = Instance.new('IntValue')	--This remembers what wings you were wearingin last.
	wingEquip.Name = 'WingEquip'
	wingEquip.Parent = saveData
	-- 0=None 1=White, 2=Blue, 3=Red, 4=Green, 5=Orange,  6=Pink, 7=Black, 8=Rainbow

	local totalDragons = Instance.new('IntValue')  --This is a count of all your dragons.
	totalDragons.Name = 'TotalDragons'
	totalDragons.Parent = saveData

	local typeTotal = Instance.new('IntValue')  --This is a count of how many dragon types you have
	typeTotal.Name = 'TypeTotal'
	typeTotal.Parent = saveData

	local reSpawn = Instance.new('IntValue')  --This is how many times you respawned.  Useful for Lobby and HotSprings.
	reSpawn.Name = 'ReSpawn'
	reSpawn.Parent = saveData

	local haveEgg = Instance.new('IntValue') --This tells what egg type you have.  0 = no egg.
	haveEgg.Name = 'HaveEgg'
	haveEgg.Parent = saveData

	local baby = Instance.new('IntValue')  --This tells what baby you hatched last.  Useful for Lobby and HotSprings.
	baby.Name = 'Baby'
	baby.Parent = saveData

	print("<<INT VALUES MADE>>")


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


	local playerUserId = 'Player_'..player.UserId


	local data
	local success, errormessage = pcall(function() -- load data
		
		--data = playerData:GetAsync(playerUserId) 
		playerData:UpdateAsync(playerUserId, function(LoadedData)
			data = LoadedData
		end) 
		if not data or not data["HaveEgg"] then
			for i = 1, SaveAttempts do
				print("No data found, retying...")
				wait(.5)
				playerData:UpdateAsync(playerUserId, function(LoadedData)
					data = LoadedData
				end) 
				
				if data and data["HaveEgg"] then
					break
				end
			end
		end 
	end)

	if success then

		if data ~= nil then  --****************This is a Returing Player who has Save Data******************************

			print("<<DATA DETECTED READY TO LOAD>>")

			--LOAD DRAGONS
			dragonWhiteAmount.Value = data['DragonWhiteAmount'] or 0
			dragonPinkAmount.Value = data['DragonPinkAmount'] or 0
			dragonBlackAmount.Value = data['DragonBlackAmount'] or 0
			dragonBlueAmount.Value = data['DragonBlueAmount'] or 0
			dragonRedAmount.Value = data['DragonRedAmount'] or 0
			dragonYellowAmount.Value = data['DragonYellowAmount'] or 0
			dragonGreenAmount.Value = data['DragonGreenAmount'] or 0
			dragonOrangeAmount.Value = data['DragonOrangeAmount'] or 0
			dragonPurpleAmount.Value = data['DragonPurpleAmount'] or 0

			--LOAD WINGS
			whiteWings.Value = data['WhiteWings'] or 0
			blueWings.Value = data['BlueWings'] or 0
			redWings.Value = data['RedWings'] or 0
			greenWings.Value = data['GreenWings'] or 0
			yellowWings.Value = data['YellowWings'] or 0
			pinkWings.Value = data['PinkWings'] or 0
			blackWings.Value = data['BlackWings'] or 0
			rainbowWings.Value = data['RainbowWings'] or 0
			
			--LOAD OTHER THINGS
			robuxSpent.Value = data['RobuxSpent'] or 0

			petEquip.Value = data['PetEquip'] or 0
			wingEquip.Value = data['WingEquip'] or 0

			reSpawn.Value = 0

			haveEgg.Value = data['HaveEgg'] or 0

			baby.Value = data['Baby'] or 0

			print("<<ALL VALUES LOADED>>")
			
			---------------------CACULATE TOTAL DRAGONS---------------------------
			totalDragons.Value = dragonWhiteAmount.Value + dragonPinkAmount.Value + dragonBlackAmount.Value +
				dragonBlueAmount.Value + dragonRedAmount.Value + dragonYellowAmount.Value + 
				dragonGreenAmount.Value + dragonOrangeAmount.Value + dragonPurpleAmount.Value
			
			print("totalDragons.Value is: " .. totalDragons.Value)
			
			---------------------CACULATE TYPE TOTAL-----------------------------
			typeTotal.Value = 0

			if dragonWhiteAmount.Value > 0 then
				typeTotal.Value += 1
			end

			if dragonPinkAmount.Value > 0 then
				typeTotal.Value += 1
			end

			if dragonBlackAmount.Value > 0 then
				typeTotal.Value += 1
			end

			if dragonBlueAmount.Value > 0 then
				typeTotal.Value += 1
			end

			if dragonRedAmount.Value > 0 then
				typeTotal.Value += 1
			end

			if dragonGreenAmount.Value > 0 then
				typeTotal.Value += 1
			end

			if dragonYellowAmount.Value > 0 then
				typeTotal.Value += 1
			end

			if dragonOrangeAmount.Value > 0 then
				typeTotal.Value += 1
			end

			if dragonPurpleAmount.Value > 0 then
				typeTotal.Value += 1
			end

			print("typeTotal.Value is: " .. typeTotal.Value)
			
			--------------------------------------------------------------------------------
			---------------<<NO DATA, set default values  Only in LOBBY!>>------------------
			--------------------------------------------------------------------------------
		else 
			print("<<NO DATA DETECTED - NEW GAME>>")

			dragonWhiteAmount.Value = 0
			dragonPinkAmount.Value = 0
			dragonBlackAmount.Value = 0
			dragonBlueAmount.Value = 0
			dragonRedAmount.Value = 0
			dragonYellowAmount.Value = 0	
			dragonGreenAmount.Value = 0
			dragonOrangeAmount.Value = 0
			dragonPurpleAmount.Value = 0

			robuxSpent.Value = 0

			whiteWings.Value = 0
			blueWings.Value = 0
			redWings.Value = 0
			greenWings.Value = 0
			yellowWings.Value = 0
			pinkWings.Value = 0
			blackWings.Value = 0
			rainbowWings.Value = 0

			petEquip.Value = 0
			wingEquip.Value = 0

			totalDragons.Value = 0

			typeTotal.Value = 0

			reSpawn.Value = 0

			haveEgg.Value = 0

			baby.Value = 0

			print("<<DATA SET TO ZERO>>")

		end
	end

	print("<<LOAD DATA ENDED>>")




	---------------------------------------------------------------------------
	----------------------------EQUIP PLAYER-----------------------------------
	---------------------------------------------------------------------------

	--FIRST MAKE SURE YOU HAVE A PLAYER CHARACTER LOADED
	--local humanoid = player.Character:FindFirstChildOfClass("Humanoid")

	local character = player.Character or 
		player.CharacterAdded:wait()

	local humanoid
	while not humanoid do
		humanoid = 
			character:FindFirstChildOfClass("Humanoid")

		if not humanoid then
			character.ChildAdded:wait()
		end
	end

	---------------------UnlimitedLives Gamepass-------------------------
	local hasPass = false

	local sucess, message = pcall(function()
		hasPass = MarketplaceService:UserOwnsGamePassAsync(player.UserId, UnlimitedLivesID)
	end)

	if hasPass == true then		
		local item = game.ReplicatedStorage.Items:FindFirstChild("UnlimitedLives"):Clone()
		item.Parent = player.Backpack
		saveData:SetAttribute("HasLives", true)
		player.PlayerGui:WaitForChild("buyGui").Enabled = false
	else
		player.PlayerGui:WaitForChild("buyGui").Enabled = true
	end
	
--[[ --This version did not work, why?	
	local hasPass = false

	local sucess, message = pcall(function()
		hasPass = player.saveData:GetAttribute("HasLives")
	end)

	if hasPass == true then		
		local item = game.ReplicatedStorage.Items:WaitForChild("UnlimitedLives"):Clone()
		item.Parent = player.Backpack
		print("*************************Unlimited Lives Loaded*************************")
		player.PlayerGui:WaitForChild("buyGui").Enabled = false
	else
		player.PlayerGui:WaitForChild("buyGui").Enabled = true
	end
]]
	-------------------------------WINGS----------------------------------

	if whiteWings.Value == 1 then
		local item = game.ReplicatedStorage.Items:FindFirstChild("WhiteWings"):Clone()
		item.Parent = player.Backpack
	end

	if blueWings.Value == 1 then
		local item = game.ReplicatedStorage.Items:FindFirstChild("BlueWings"):Clone()
		item.Parent = player.Backpack
	end

	if redWings.Value == 1 then
		local item = game.ReplicatedStorage.Items:FindFirstChild("RedWings"):Clone()
		item.Parent = player.Backpack
	end

	if greenWings.Value == 1 then
		local item = game.ReplicatedStorage.Items:FindFirstChild("GreenWings"):Clone()
		item.Parent = player.Backpack
	end

	if yellowWings.Value == 1 then
		local item = game.ReplicatedStorage.Items:FindFirstChild("YellowWings"):Clone()
		item.Parent = player.Backpack
	end

	if pinkWings.Value == 1 then
		local item = game.ReplicatedStorage.Items:FindFirstChild("PinkWings"):Clone()
		item.Parent = player.Backpack
	end

	if blackWings.Value == 1 then
		local item = game.ReplicatedStorage.Items:FindFirstChild("BlackWings"):Clone()
		item.Parent = player.Backpack
	end

	if rainbowWings.Value == 1 then
		local item = game.ReplicatedStorage.Items:FindFirstChild("RainbowWings"):Clone()
		item.Parent = player.Backpack
	end

	-------------------------------EQUIP WINGS----------------------------------
	-----------------------------------------------------------------------------
	-- 0=None 1=White, 2=Blue, 3=Red, 4=Green, 5=Yellow,  6=Pink, 7=Black, 8=Rainbow
	print("****************About to equip wings*********************")
	if wingEquip.Value == 1 then
		print("****************WHITE WINGS Detected*********************")
		local tool = player.Backpack:FindFirstChild("WhiteWings")
		humanoid:EquipTool(tool)
		print("****************WHITE WINGS Equiped*********************")

	elseif wingEquip.Value == 2 then

		local tool = player.Backpack:FindFirstChild("BlueWings")
		humanoid:EquipTool(tool)

	elseif wingEquip.Value == 3 then

		local tool = player.Backpack:FindFirstChild("RedWings")
		humanoid:EquipTool(tool)

	elseif wingEquip.Value == 4 then

		local tool = player.Backpack:FindFirstChild("GreenWings")
		humanoid:EquipTool(tool)

	elseif wingEquip.Value == 5 then

		local tool = player.Backpack:FindFirstChild("YellowWings")
		humanoid:EquipTool(tool)

	elseif wingEquip.Value == 6 then

		local tool = player.Backpack:FindFirstChild("PinkWings")
		humanoid:EquipTool(tool)

	elseif wingEquip.Value== 7 then

		local tool = player.Backpack:FindFirstChild("BlackWings")
		humanoid:EquipTool(tool)

	elseif wingEquip.Value == 8 then

		local tool = player.Backpack:FindFirstChild("RainbowWings")
		humanoid:EquipTool(tool)

	end

	-----------------------------------------------------------
	---------------------PANCHOS LEADERBOARD-------------------
	-------------------------LOBBY ONLY------------------------
	-----------------------------------------------------------

	local success, err = pcall(function()

		dataStore: SetAsync(player.UserId, totalDragons.Value)
		print("<<Saved PANCHOS LEADERBOARD data for " ..player.Name.. ".>>")
		print("<<totalDragons.Value is for leaderboard is " ..totalDragons.Value.. ".>>")
	end)

	if not success then
		print("<<FAILED to save PANCHOS LEADERBOARD data for " ..player.Name.. ".>>")
		warn(err)
	end
	------------------------------------------------------------
	------------------------------------------------------------

--[[
    --------------------------------------------------------------------------
	---------------------CREATE PET AND SET PLAYER BUTTONS--------------------
	---------------------------RESCUE MISSION ONLY----------------------------
	--------------------------------------------------------------------------

	if player.saveData.TotalDragons.Value >= 1 then -- If I have a dragon,
		
		local ReplicatedStorage = game:GetService('ReplicatedStorage')
		local spawnPetEvent = ReplicatedStorage.Remotes:WaitForChild('spawnPetEvent')
		spawnPetEvent:Fire(player)  --spawn dragon
		
		
		player.PlayerGui.openMyDragonsGui.Enabled = true  --give menu to see.
		print("**********************Can open My Dragons****************************")
	else
		player.PlayerGui.openMyDragonsGui.Enabled = false
		print("**********************Can NOT open My Dragons****************************")
	end


	player.PlayerGui.inviteGui.Enabled = false 
	print("**********************INVITE CLOSED****************************")
	
]]

	-------------------------------EQUIP Egg----------------------------------
	-- 0 = None 1 = Easy, 2 = Hard, 3 = Impossible
	----------------------------------------------------------------------------
	--Lobby
	player.saveData.HaveEgg.Value = 0
	--Testing
	--player.saveData.HaveEgg.Value = 2
--[[
	print("****************About to equip Egg*********************")
	if player.saveData.HaveEgg.Value == 1 then
		local Egg = game.ReplicatedStorage.EggEasy
		local clonedItem = Egg:Clone ()
		clonedItem.Handle. Anchored = false
		humanoid: AddAccessory (clonedItem)
		print("****************Easy Egg Equipped*********************")
	elseif player.saveData.HaveEgg.Value == 2 then
		local Egg = game.ReplicatedStorage.EggHard
		local clonedItem = Egg:Clone ()
		clonedItem.Handle. Anchored = false
		humanoid: AddAccessory (clonedItem)
		print("****************Hard Egg Equipped*********************")
	elseif player.saveData.HaveEgg.Value == 3 then
		local Egg = game.ReplicatedStorage.EggImpossible
		local clonedItem = Egg:Clone ()
		clonedItem.Handle. Anchored = false
		humanoid: AddAccessory (clonedItem)
		print("****************Impossible Egg Equipped*********************")
	end	
	-------------------------------------------------------------------------
	-------------------------------------------------------------------------
]]	
--[[
	-- autosave
	while wait(AutosaveInterval) do -- autosave
		SaveData(player)
	end
	]]
end

---------------------------------------------------------------------------
----------------------------PLAYER EXITS - SAVE DATA-----------------------
---------------------------------------------------------------------------


local function onPlayerExit(player) -- saving until no errors
	local success, err = SaveData(player)

	if not success then
		print("<<FAILED to save onPlayerExit data for " ..player.Name.. ".>>")
		warn(err)
		for i = 1, SaveAttempts do
			wait(.5)
			local success, err = SaveData(player)
			if success then
				break
			else
				warn(err)
			end
		end
	end
end

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


game.Players.PlayerAdded:Connect(onPlayerJoin)
game.Players.PlayerRemoving:Connect(onPlayerExit)


----------------------<<REMOTE SAVE>>------------------------
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local SaveGameBE = ReplicatedStorage.Remotes:WaitForChild('SaveGameBE')
SaveGameBE.Event:Connect(SaveData)
1 Like

You can consider switching to DataStore2 which should avoid all your data loss problems

Hi Souly, yes I will consider DataStore2. Thank you. But first, I want to see if it is possible to use the regular datastore correctly. Is the regular data store truly unstable/unusable? I want to know if I am making an error that can be corrected. Thank you again.

I’m going to presume one or more of the conditional checks which gate-keep the execution of certain lines of code are not being satisfied in certain scenarios, resulting in the loss of data of various players.

Thank you Forummer. This is my first time really using save data (more then a leaderboard). I was not sure if there was something fundamentally flawed with Roblox default save system, or I’m making some mistakes. Perhaps there is something wrong with my gatekeeping, like you are suggesting. Could you or anyone advise me the best way to check for new players (those with no data). I check 5 times, with .5 seconds delays, and if it returns no data, I declare the player new, and eligible for default save values. Is this reasonable, or how do others check for a new player? Thank you.