DataStore2 does not work properly when using TeleportService

  1. What do you want to achieve? I would like to solve the problem in the title.

  2. What is the issue? If I use TeleportService, it will lose all the progress you made on that server

  3. What solutions have you tried so far? I tried every solution I could think of right away, such as delaying teleportation, saving player data before teleporting, etc.

Here is the Code that manages the data

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")

local DataStore2 = require(ServerScriptService.DataStore2)

DataStore2.Combine("DATA" ,"AchievementStore", "AmuletStore10", "AmuletPowerStore", "Damage", "EquipStore4", "PetEquipStore", "MaterialStore", "ScoreStore2", "SlotStore2", "SpiritStore", "UpgradeStore2", "XP", "PetStore", "MountStore", "QuestStore3", "Setting", "Boolean")

Players.PlayerAdded:Connect(function(Player)

	-- Tables
	local AchievementTable = {}
	local AmuletTable = {}
	local MaterialTable = {}
	local ScoreTable = {}
	local SlotTable = {
		["Slot1"] = "None",
		["Slot2"] = "None",
		["Slot3"] = "None",
		["Slot4"] = "None",
		["Slot5"] = "None"
	}
	local SpiritTable = {}
	local UpgradeTable = {
		["Core"] = {};
	}
	local PetTable = {}
	local MountTable = {}
	local QuestTable = {}
	local SettingTable = {}
	local BooleanTable = {
		["DoubleXP"] = false;
		["EquippedBasicAmulet"] = false;

		["FireSpiritBunny"] = false;
		["FireSpiritEgg"] = false;

		["IceSpiritBunny"] = false;
		["IceSpiritEgg"] = false;

		["HoneyBeeChick"] = false;

		["IceCreamAmulet"] = false;
		["MagicalEggAmulet"] = false;
		["BunnyEggAmulet"] = false;

		["EquippedFireSpiritBunny"] = false;
		["EquippedFireSpiritEgg"] = false;

		["EquippedIceSpiritBunny"] = false;
		["EquippedIceSpiritEgg"] = false;

		["EquippedHoneyBeeChick"] = false;

		["EquippedIceCreamAmulet"] = false;
		["EquippedMagicalEggAmulet"] = false;
		["EquippedBunnyEggAmulet"] = false;
	}
	--

	-- Get Folders
	repeat
		wait()
	until Player:FindFirstChild("Leaderstats"):FindFirstChild("Mount") and Player:FindFirstChild("Leaderstats"):FindFirstChild("Pet") and Player:FindFirstChild("Leaderstats"):FindFirstChild("Upgrade") and Player:FindFirstChild("Leaderstats"):FindFirstChild("Spirit") and Player:FindFirstChild("Leaderstats"):FindFirstChild("Slot") and Player:FindFirstChild("Leaderstats"):FindFirstChild("Score") and Player:FindFirstChild("Leaderstats"):FindFirstChild("Achievement") and Player:FindFirstChild("Leaderstats"):FindFirstChild("Amulet") and Player:FindFirstChild("Leaderstats"):FindFirstChild("Character") and Player:FindFirstChild("Leaderstats"):FindFirstChild("Material")
	--

	-- Folders
	local AchievementFolder = Player.Leaderstats.Achievement
	local AmuletFolder = Player.Leaderstats.Amulet
	local Character = Player:FindFirstChild("Leaderstats"):FindFirstChild("Character")
	local AmuletName = 0
	local PetName = 0
	local MountName = 0
	local MaterialFolder = Player.Leaderstats.Material
	local ScoreFolder = Player.Leaderstats.Score
	local SlotFolder = Player.Leaderstats.Slot
	local SpiritFolder = Player.Leaderstats.Spirit
	local UpgradeFolder = Player.Leaderstats.Upgrade
	local PetFolder = Player.Leaderstats.Pet
	local MountFolder = Player.Leaderstats.Mount
	local QuestFolder = Player.Leaderstats.Quest
	local SettingFolder = Player.Leaderstats.Setting
	local BooleanFolder = Player.Leaderstats.Boolean
	--

	-- Instances
	local Damage = Instance.new("IntValue", Character); Damage.Name = "TotalDamage"
	local XPValue = Instance.new("IntValue", Character); XPValue.Name = "XP"
	local RankValue = Instance.new("IntValue", Character); RankValue.Name = "Rank"
	local Slot1 = Instance.new("StringValue", SlotFolder); Slot1.Name = "1"; Slot1.Value = "None"
	local Slot2 = Instance.new("StringValue", SlotFolder); Slot2.Name = "2"; Slot2.Value = "None"
	local Slot3 = Instance.new("StringValue", SlotFolder); Slot3.Name = "3"; Slot3.Value = "None"
	local Slot4 = Instance.new("StringValue", SlotFolder); Slot4.Name = "4"; Slot4.Value = "None"
	local Slot5 = Instance.new("StringValue", SlotFolder); Slot5.Name = "5"; Slot5.Value = "None"
	--

	-- DataStores
	local AchievementStore = DataStore2("AchievementStore", Player)
	local AmuletStore = DataStore2("AmuletStore10", Player)
	local DamageStore = DataStore2("Damage", Player)
	local EquipStore = DataStore2("EquipStore4", Player)
	local PetEquipStore = DataStore2("PetEquipStore", Player)
	local MountEquipStore = DataStore2("MountEquipStore", Player)
	local MaterialStore = DataStore2("MaterialStore", Player)
	local ScoreStore = DataStore2("ScoreStore2", Player)
	local SlotStore = DataStore2("SlotStore2", Player)
	local SpiritStore = DataStore2("SpiritStore", Player)
	local UpgradeStore = DataStore2("UpgradeStore2", Player)
	local XPStore = DataStore2("XP", Player)
	local PetStore = DataStore2("PetStore", Player)
	local MountStore = DataStore2("MountStore", Player)
	local QuestStore = DataStore2("QuestStore3", Player)
	local SettingStore = DataStore2("Setting", Player)
	local BooleanStore = DataStore2("Boolean", Player)
	--

	-- Updates
	local function AchievementUpdate(Value)
		AchievementTable = AchievementStore:Get(Value)

		for i, v in ipairs(AchievementTable) do
			if not AchievementFolder:FindFirstChild(v) then
				local New = Instance.new("BoolValue", AchievementFolder); New.Name = v
			end
		end
	end
	--
	local function AmuletUpdate(Value)
		AmuletTable = AmuletStore:GetTable(Value)
		AmuletFolder:ClearAllChildren()

		for i, v in pairs(AmuletTable) do
			
			if v["A1"] == "Range" then
				if v["V1"] >= 1.6 then
					v["V1"] = 1.6
				end 
			end

			if v["A2"] == "Range" then
				if v["V2"] >= 1.6 then
					v["V2"] = 1.6
				end 
			end

			if v["A3"] == "Range" then
				if v["V3"] >= 1.6 then
					v["V3"] = 1.6
				end 
			end

			local New = Instance.new("BoolValue", AmuletFolder); New.Name = v.Amulet
			local A1 = Instance.new("NumberValue", New); A1.Name = v["A1"]; A1.Value = v["V1"]
			local A2 = Instance.new("NumberValue", New); A2.Name = v["A2"]; A2.Value = v["V2"]
			local A3 = Instance.new("NumberValue", New); A3.Name = v["A3"]; A3.Value = v["V3"]

			local NC1 = Instance.new("NumberValue", New); NC1.Name = "C1"; NC1.Value = v["C1"]
			local NC2 = Instance.new("NumberValue", New); NC2.Name = "C2"; NC2.Value = v["C2"]
			local NC3 = Instance.new("NumberValue", New); NC3.Name = "C3"; NC3.Value = v["C3"]


			local RM = Instance.new("StringValue", New); RM.Name = "RM"; RM.Value = v["RM"]

		end
	end
	--
	local function DamageUpdate(Value)
		Player.Leaderstats.Character.TotalDamage.Value = Value
	end
	--
	local function EquipUpdate(Value)
		AmuletName = EquipStore:Get(Value)
		game.ReplicatedStorage.RemoteEvent.EquipAmulet.Server:Fire(Player, AmuletName)
	end
	--
	local function PetEquipUpdate(Value)
		PetName = PetEquipStore:Get(Value)
		game.ReplicatedStorage.RemoteEvent.EquipPet.Server:Fire(Player, PetName)
	end
	--
	local function MountEquipUpdate(Value)
		MountName = MountEquipStore:Get(Value)
		if Value ~= 0 then
			game.ReplicatedStorage.RemoteEvent.EquipMount.Server:Fire(Player, MountName, "Equip")
		else
			game.ReplicatedStorage.RemoteEvent.EquipMount.Server:Fire(Player, MountName, "Unequip")
		end
	end
	--
	local function MaterialUpdate(Value)
		MaterialTable = MaterialStore:Get(Value)

		for i, v in ipairs(MaterialTable) do
			local Alr = Player.Leaderstats.Material:FindFirstChild(v["Name"])

			if v["Name"] == "None" then
				table.remove(MaterialTable, i)
			end

			if Alr then

				Alr.Value = v["Value"]
			else
				local nM = Instance.new("IntValue", MaterialFolder); nM.Name = v["Name"]; nM.Value = v["Value"]
			end

		end
	end
	--
	local function ScoreUpdate(Value)
		ScoreTable = ScoreStore:GetTable(Value)

		for i, v in ipairs(ScoreTable) do
			local Alr = Player.Leaderstats.Score:FindFirstChild(v["Name"])
			if Alr then
				Alr.Value = v["Value"]
			else
				local nS = Instance.new("IntValue", ScoreFolder); nS.Name = v["Name"]; nS.Value = v["Value"]	
			end

		end
	end
	--
	local function SlotUpdate(Value)
		SlotTable = SlotStore:GetTable(Value)
		Slot1.Value = SlotTable["Slot1"]; game.ReplicatedStorage.RemoteEvent.EquipfromData:FireClient(Player, "1", SlotTable["Slot1"])
		Slot2.Value = SlotTable["Slot2"]; game.ReplicatedStorage.RemoteEvent.EquipfromData:FireClient(Player, "2", SlotTable["Slot2"])
		Slot3.Value = SlotTable["Slot3"]; game.ReplicatedStorage.RemoteEvent.EquipfromData:FireClient(Player, "3", SlotTable["Slot3"])
		Slot4.Value = SlotTable["Slot4"]; game.ReplicatedStorage.RemoteEvent.EquipfromData:FireClient(Player, "4", SlotTable["Slot4"])
		Slot5.Value = SlotTable["Slot5"]; game.ReplicatedStorage.RemoteEvent.EquipfromData:FireClient(Player, "5", SlotTable["Slot5"])
	end
	--
	local function SpiritUpdate(Value)
		SpiritTable = SpiritStore:GetTable(Value)

		for i, v in ipairs(SpiritTable) do
			local Alr = Player.Leaderstats.Spirit:FindFirstChild(v["Name"])
			if Alr then
				Alr.Value = v["Value"]
			else
				local nS = Instance.new("IntValue", SpiritFolder); nS.Name = v["Name"]; nS.Value = v["Value"]
			end

		end
	end
	--
	local function UpgradeUpdate(Value)
		UpgradeTable = UpgradeStore:GetTable(Value)

		for i, v in pairs(UpgradeTable.Core) do

			local Alr = Player.Leaderstats.Upgrade.Core:FindFirstChild(v["Name"])
			if Alr then
			else
				local nC = Instance.new("BoolValue", UpgradeFolder.Core); nC.Name = v["Name"];
			end

		end
	end
	--
	local function XPUpdate(Value)
		Player.Leaderstats.Character.XP.Value = Value
		local DS = DataStore2("XP", Player)
		DS:Set(Value)
	end
	--
	local function PetUpdate(Value)
		PetTable = PetStore:GetTable(Value)

		for i, v in ipairs(PetTable) do
			local Alr = Player.Leaderstats.Pet:FindFirstChild(v["Name"])
			if Alr then
				Alr.Value = v["Value"]
			else
				local New = Instance.new("IntValue", PetFolder); New.Name = v["Name"]; New.Value = v["Value"]	
			end

		end
	end
	--
	local function MountUpdate(Value)
		MountTable = MountStore:GetTable(Value)

		for i, v in ipairs(MountTable) do
			local Alr = Player.Leaderstats.Mount:FindFirstChild(v["Name"])
			if Alr then
				Alr.Value = v["Value"]
			else
				local New = Instance.new("IntValue", MountFolder); New.Name = v["Name"]; New.Value = v["Value"]	
			end

		end
	end
	--
	local function QuestUpdate(Value)
		QuestTable = QuestStore:GetTable(Value)
		local QN = nil
		local Alr = false

		if #QuestTable ~= 0 then

			if #QuestFolder:GetChildren() < 1 then

				for i, v in pairs(QuestTable) do

					for ii, vv in pairs(v) do

						if ii == "QuestName" then


							QN = Instance.new("BoolValue", QuestFolder); QN.Name = vv
						end
					end						
				end
			else
				Alr = true
			end


			if Alr == false then
				for i, v in pairs(QuestTable) do

					for ii, vv in pairs(v) do

						if ii ~= "QuestName" then

							if not QN:FindFirstChild(v[1]) then

								local Req = Instance.new("IntValue", QN); Req.Name = v[1]
								local Scr = game.ReplicatedStorage["Quest Script"]:FindFirstChild(Req.Name):Clone(); Scr.Parent = Player.Character
								Scr.Quest.Value = QN.Name

								Req.Value = v[2]
								Scr.Disabled = false
							end
						end
					end
				end
			end

		else
			QuestFolder:ClearAllChildren()
		end
	end
	--
	local function SettingUpdate(Value)
		SettingTable = SettingStore:GetTable(Value)

		for i, v in ipairs(SettingTable) do
			
			if SettingFolder:FindFirstChild(v["Name"]) then
				SettingFolder:FindFirstChild(v["Name"]).Value = v["Value"]
			end

		end
	end
	--
	local function BooleanUpdate(Value)
		BooleanTable = BooleanStore:GetTable(Value)
		BooleanFolder:ClearAllChildren()

		for i, v in pairs(BooleanTable) do

			local Boolean = Instance.new("BoolValue", BooleanFolder); Boolean.Name = i; Boolean.Value = v
	

		end
	end
	--

	-- Call
	ScoreUpdate(ScoreTable)
	ScoreStore:OnUpdate(ScoreUpdate)
	AchievementUpdate(AchievementTable)
	AchievementStore:OnUpdate(AchievementUpdate)
	AmuletUpdate(AmuletTable)
	AmuletStore:OnUpdate(AmuletUpdate)
	DamageUpdate(DamageStore:Get(0))
	DamageStore:OnUpdate(DamageUpdate)
	EquipUpdate(EquipStore:Get(0))
	EquipStore:OnUpdate(EquipUpdate)
	PetEquipUpdate(PetEquipStore:Get(0))
	PetEquipStore:OnUpdate(PetEquipUpdate)
	MountEquipUpdate(MountEquipStore:Get(0))
	MountEquipStore:OnUpdate(MountEquipUpdate)
	MaterialUpdate(MaterialTable)
	MaterialStore:OnUpdate(MaterialUpdate)
	SlotUpdate(SlotTable)
	SlotStore:OnUpdate(SlotUpdate)
	SpiritUpdate(SpiritTable)
	SpiritStore:OnUpdate(SpiritUpdate)
	UpgradeUpdate(UpgradeTable)
	UpgradeStore:OnUpdate(UpgradeUpdate)
	XPUpdate(XPStore:Get(0))
	XPStore:OnUpdate(XPUpdate)
	PetUpdate(PetTable)
	PetStore:OnUpdate(PetUpdate)
	MountUpdate(MountTable)
	MountStore:OnUpdate(MountUpdate)
	QuestUpdate(QuestTable)
	QuestStore:OnUpdate(QuestUpdate)
	SettingUpdate(SettingTable)
	SettingStore:OnUpdate(SettingUpdate)
	BooleanUpdate(BooleanTable)
	BooleanStore:OnUpdate(BooleanUpdate)
	--

end)

-- Action
local function AchievementA(Player, Name)

	local DS = DataStore2("AchievementStore", Player)

	local Table = {}

	local Folder = Player.Leaderstats.Achievement

	if not Folder:FindFirstChild(Name) then

		local New = Instance.new("BoolValue", Folder); New.Name = Name

		for i, v in pairs(Player.Leaderstats.Achievement:GetChildren()) do
			table.insert(Table, v.Name)
		end

		DS:Set(Table)


	end
end
--
local function AmuletA(Player, ValueName, A1, A2, A3, V1, V2, V3, C1, C2, C3)

	if Player.Backpack.Character.MaxAmulet.Value > #Player.Leaderstats.Amulet:GetChildren() then

		local DS = DataStore2("AmuletStore10", Player)

		local Folder = Player.Leaderstats.Amulet

		local Table = {}

		local New = Instance.new("BoolValue", Folder); New.Name = ("Amulet" .. " #" .. #Player.Leaderstats.Amulet:GetChildren())
		local NA1 = Instance.new("NumberValue", New); NA1.Name = A1; NA1.Value = V1
		local NA2 = Instance.new("NumberValue", New); NA2.Name = A2; NA2.Value = V2
		local NA3 = Instance.new("NumberValue", New); NA3.Name = A3; NA3.Value = V3

		local NC1 = Instance.new("NumberValue", New); NC1.Name = "C1"; NC1.Value = C1
		local NC2 = Instance.new("NumberValue", New); NC2.Name = "C2"; NC2.Value = C2
		local NC3 = Instance.new("NumberValue", New); NC3.Name = "C3"; NC3.Value = C3

		local RM = Instance.new("StringValue", New); RM.Name = "RM"; RM.Value = RM


		table.insert(Table, {["Amulet"] = New.Name, ["A1"] = NA1.Name, ["A2"] = NA2.Name, ["A3"] = NA3.Name, ["V1"] = NA1.Value, ["V2"] = NA2.Value, ["V3"] = NA3.Value, ["C1"] = NC1.Value, ["C2"] = NC2.Value, ["C3"] = NC3.Value, ["RM"] = RM.Value})
		DS:Set(Table)



	end
end
--
local function Discard(Player)
	local DataStore = DataStore2("AmuletStore10", Player)

	local Table = {}

	local Location = Player.Leaderstats.Amulet
	Location:ClearAllChildren()
	DataStore:Set(Table)

	if Player.Character:FindFirstChild("Equipped") then
		Player.Character:FindFirstChild("Equipped"):Destroy()
	end
end
--
local function EquipA(Player, AmuletName)

	local DataStore = DataStore2("EquipStore4", Player)

	local AmuletName = AmuletName

	DataStore:Set(AmuletName)

end
--
local function PetEquipA(Player, PetName)

	local DataStore = DataStore2("PetEquipStore", Player)

	local PetName = PetName

	DataStore:Set(PetName)

end
--
local function MountEquipA(Player, MountName)

	local DataStore = DataStore2("MountEquipStore", Player)

	DataStore:Set(MountName)

end
--
local function MaterialA(Player, ValueName, Value, Negative)
	local DataStore = DataStore2("MaterialStore", Player)

	local Material = Player.Leaderstats.Material
	local AlrMaterial = Material:FindFirstChild(ValueName)

	local MTable = {}

	if AlrMaterial then

		if Negative == true then
			AlrMaterial.Value = AlrMaterial.Value - Value

			for i, v in ipairs(Material:GetChildren()) do
				table.insert(MTable, {["Name"] = v.Name, ["Value"] = v.Value})
			end
			DataStore:Set(MTable)



		else

			AlrMaterial.Value = AlrMaterial.Value + Value
			for i, v in ipairs(Material:GetChildren()) do
				table.insert(MTable, {["Name"] = v.Name, ["Value"] = v.Value})
			end
			DataStore:Set(MTable)

		end



	else
		local NMaterial = Instance.new("IntValue", Player.Leaderstats.Material); NMaterial.Value = NMaterial.Value + Value; NMaterial.Name = ValueName
		for i, v in ipairs(Material:GetChildren()) do
			table.insert(MTable, {["Name"] = v.Name, ["Value"] = v.Value})
		end
		DataStore:Set(MTable)
	end

end
--
local function ScoreA(Player, ValueName, Value)
	local DataStore = DataStore2("ScoreStore2", Player)

	local Score = Player.Leaderstats.Score
	local AlrScore = Score:FindFirstChild(ValueName)

	local STable = {}

	if AlrScore then
		AlrScore.Value = AlrScore.Value + Value
		for i, v in ipairs(Score:GetChildren()) do
			table.insert(STable, {["Name"] = v.Name, ["Value"] = v.Value})
		end
		DataStore:Set(STable)
	else
		local NScore = Instance.new("IntValue", Player.Leaderstats.Score); NScore.Value = NScore.Value + Value; NScore.Name = ValueName
		for i, v in ipairs(Score:GetChildren()) do
			table.insert(STable, {["Name"] = v.Name, ["Value"] = v.Value})
		end
		DataStore:Set(STable)
	end
end
--
local function SpiritA(Player, ValueName, Value)

	local DataStore = DataStore2("SpiritStore", Player)

	local Spirit = Player.Leaderstats.Spirit
	local AlrSpirit = Spirit:FindFirstChild(ValueName)

	local STable = {}

	if AlrSpirit then
		AlrSpirit.Value = AlrSpirit.Value + Value
		for i, v in ipairs(Spirit:GetChildren()) do
			table.insert(STable, {["Name"] = v.Name, ["Value"] = v.Value})
		end
		DataStore:Set(STable)
	else
		local NSpirit = Instance.new("IntValue", Player.Leaderstats.Spirit); NSpirit.Value = NSpirit.Value + Value; NSpirit.Name = ValueName
		for i, v in ipairs(Spirit:GetChildren()) do
			table.insert(STable, {["Name"] = v.Name, ["Value"] = v.Value})
		end
		DataStore:Set(STable)
	end

end
--
local function UpgradeA(Player, ValueName, UpgradeType)
	local DataStore = DataStore2("UpgradeStore2", Player)

	local Upg = Player.Leaderstats.Upgrade

	local Table = {
		["Core"] = {};
	}

	if UpgradeType == "Core" then

		if Player.Leaderstats.Material:FindFirstChild("Golem Core") then

			if Player.Leaderstats.Material:FindFirstChild("Golem Core").Value >= 1 then

				Player.Leaderstats.Material:FindFirstChild("Golem Core").Value = Player.Leaderstats.Material:FindFirstChild("Golem Core").Value - 1

				local Alr = Upg.Core:FindFirstChild(ValueName)

				if not Alr then

					local nC = Instance.new("BoolValue", Upg.Core); nC.Name = ValueName
					for i, v in pairs(Upg.Core:GetChildren()) do

						table.insert(Table.Core, {["Name"] = v.Name})
					end
				end
			end
			DataStore:Set(Table)
		end
	end
end
--
local function PetA(Player, ValueName, Value)
	local DataStore = DataStore2("PetStore", Player)

	local Folder = Player.Leaderstats.Pet
	local Alr = Folder:FindFirstChild(ValueName)

	local Table = {}

	if Alr then
		Alr.Value = Alr.Value + Value
		for i, v in ipairs(Folder:GetChildren()) do
			table.insert(Table, {["Name"] = v.Name, ["Value"] = v.Value})
		end
		DataStore:Set(Table)
	else
		local New = Instance.new("IntValue", Player.Leaderstats.Pet); New.Value = New.Value + Value; New.Name = ValueName
		for i, v in ipairs(Folder:GetChildren()) do
			table.insert(Table, {["Name"] = v.Name, ["Value"] = v.Value})
		end
		DataStore:Set(Table)
	end
end
--
local function MountA(Player, ValueName, Value)

	local DataStore = DataStore2("MountStore", Player)

	local Folder = Player.Leaderstats.Mount
	local Alr = Folder:FindFirstChild(ValueName)

	local Table = {}

	if Alr then
		Alr.Value = Alr.Value + Value
		for i, v in ipairs(Folder:GetChildren()) do
			table.insert(Table, {["Name"] = v.Name, ["Value"] = v.Value})
		end
		DataStore:Set(Table)
	else
		local New = Instance.new("IntValue", Player.Leaderstats.Mount); New.Value = New.Value + Value; New.Name = ValueName
		for i, v in ipairs(Folder:GetChildren()) do
			table.insert(Table, {["Name"] = v.Name, ["Value"] = v.Value})
		end
		DataStore:Set(Table)
	end
end
--
local function QuestA(Player, QuestName)

	local DataStore = DataStore2("QuestStore3", Player)
	local Table = {}


	if QuestName ~= 0 and QuestName ~= "0" then


		table.insert(Table, {["QuestName"] = QuestName})


		if not Player.Leaderstats.Quest:FindFirstChild(QuestName) then

			local QN = Instance.new("BoolValue", Player.Leaderstats.Quest); QN.Name = QuestName


			for i, v in pairs(game.ReplicatedStorage.UI.QuestFrame:FindFirstChild(QuestName).Require:GetChildren()) do

				local Req = Instance.new("IntValue", QN); Req.Name = v.Name

			end

		end


		for i, v in pairs(Player.Leaderstats.Quest:FindFirstChild(QuestName):GetChildren()) do

			table.insert(Table, i, {v.Name, v.Value})

		end


		DataStore:Set(Table)

	else
		DataStore:Set(Table)

	end
end
--
local function SettingA(Player)

	local DataStore = DataStore2("Setting", Player)

	local Folder = Player.Leaderstats.Setting

	local Table = {}
	
	
	for i, v in pairs(Folder:GetChildren()) do
		table.insert(Table, {["Name"] = v.Name, ["Value"] = v.Value})
	end
	DataStore:Set(Table)

end
--
local function BooleanA(Player)

	local DataStore = DataStore2("Boolean", Player)

	local Folder = Player.Leaderstats.Boolean

	local BooleanTable = {
		["DoubleXP"] = false;
		["EquippedBasicAmulet"] = false;

		["FireSpiritBunny"] = false;
		["FireSpiritEgg"] = false;

		["IceSpiritBunny"] = false;
		["IceSpiritEgg"] = false;

		["HoneyBeeChick"] = false;

		["IceCreamAmulet"] = false;
		["MagicalEggAmulet"] = false;
		["BunnyEggAmulet"] = false;

		["EquippedFireSpiritBunny"] = false;
		["EquippedFireSpiritEgg"] = false;

		["EquippedIceSpiritBunny"] = false;
		["EquippedIceSpiritEgg"] = false;

		["EquippedHoneyBeeChick"] = false;

		["EquippedIceCreamAmulet"] = false;
		["EquippedMagicalEggAmulet"] = false;
		["EquippedBunnyEggAmulet"] = false;
	}
	
	for i, v in pairs(BooleanTable) do
		BooleanTable[i] = Folder:FindFirstChild(i).Value
	end

	DataStore:Set(BooleanTable)

end
--

-- Events
game.ReplicatedStorage.RemoteEvent.AchievementUpdate.Server.Event:Connect(AchievementA)
game.ReplicatedStorage.RemoteEvent.AmuletUpdate.OnServerEvent:Connect(AmuletA); game.ReplicatedStorage.RemoteEvent.AmuletUpdate.Server.Event:Connect(AmuletA)
game.ReplicatedStorage.RemoteEvent.DiscardAmulet.OnServerEvent:Connect(Discard)
game.ReplicatedStorage.RemoteEvent.AmuletEquip.OnServerEvent:Connect(EquipA); game.ReplicatedStorage.RemoteEvent.AmuletEquip.Server.Event:Connect(EquipA)
game.ReplicatedStorage.RemoteEvent.EquipPetUpdate.OnServerEvent:Connect(PetEquipA); game.ReplicatedStorage.RemoteEvent.EquipPetUpdate.Server.Event:Connect(PetEquipA)
game.ReplicatedStorage.RemoteEvent.EquipMountUpdate.OnServerEvent:Connect(MountEquipA); game.ReplicatedStorage.RemoteEvent.EquipMountUpdate.Server.Event:Connect(MountEquipA)
game.ReplicatedStorage.RemoteEvent.MaterialUpdate.OnServerEvent:Connect(MaterialA); game.ReplicatedStorage.RemoteEvent.MaterialUpdate.Server.Event:Connect(MaterialA)
game.ReplicatedStorage.RemoteEvent.ScoreUpdate.OnServerEvent:Connect(ScoreA);game.ReplicatedStorage.RemoteEvent.ScoreUpdate.Server.Event:Connect(ScoreA)
game.ReplicatedStorage.RemoteEvent.SpiritUpdate.OnServerEvent:Connect(SpiritA); game.ReplicatedStorage.RemoteEvent.SpiritUpdate.Server.Event:Connect(SpiritA)
game.ReplicatedStorage.RemoteEvent.UpgradeUpdate.OnServerEvent:Connect(UpgradeA); game.ReplicatedStorage.RemoteEvent.UpgradeUpdate.Server.Event:Connect(UpgradeA)
game.ReplicatedStorage.RemoteEvent.PetUpdate.OnServerEvent:Connect(PetA); game.ReplicatedStorage.RemoteEvent.PetUpdate.Server.Event:Connect(PetA)
game.ReplicatedStorage.RemoteEvent.MountUpdate.OnServerEvent:Connect(MountA); game.ReplicatedStorage.RemoteEvent.MountUpdate.Server.Event:Connect(MountA)
game.ReplicatedStorage.RemoteEvent.QuestUpdate.OnServerEvent:Connect(QuestA); game.ReplicatedStorage.RemoteEvent.QuestUpdate.Server.Event:Connect(QuestA)
game.ReplicatedStorage.RemoteEvent.SettingUpdate.OnServerEvent:Connect(SettingA); game.ReplicatedStorage.RemoteEvent.SettingUpdate.Server.Event:Connect(SettingA)
game.ReplicatedStorage.RemoteEvent.BooleanUpdate.OnServerEvent:Connect(BooleanA); game.ReplicatedStorage.RemoteEvent.BooleanUpdate.Server.Event:Connect(BooleanA)

--

Code that brings the player back to the lobby ((The data doesn’t behave properly after executing this Code.))

local TeS = game:GetService("TeleportService")
local Players = game:GetService("Players")

game.ReplicatedStorage.RemoteEvent.Exit.OnServerEvent:Connect(function(Player, UserID, PlaceID)

	pcall(function()
		local ServerScriptService = game:GetService("ServerScriptService")
		local DataStore2 = require(ServerScriptService.DataStore2)
		DataStore2:SaveAll(Player)
	end)

	wait(5)
	local Plr = Players:GetPlayerByUserId(UserID)
	TeS:Teleport(PlaceID, Plr)
end)

with the Roblox regular leave button, this problem does not occur at all

As you all know, DataStore2 saves every time a value changes, so why is data lost in the process of returning a player to the lobby?

This is strange, too, because sometimes it is saved well

Here’s a brief, one-way explanation.
This is a Tower Defense game, and when you finish defeating a boss, you get an Exit button (back to the lobby), and when you press it, all the XP and data you gained in that server will be lost, and you will be returned to the lobby.

I’ve tried everything I can try, and I’ve looked around on the Dev Forum, but I can’t find a satisfactory answer.

This is a problem I have been having for several months now. I posted this in the hope that i can find some clues.

1 Like

Um, I am not seeing why your thing doesn’t save. My game is structured similar to TDS, but for racing, and I use a script like this:

local DataStore2 = require(game:GetService("ServerScriptService").DataStore2)
local CombinedDataStore = DataStore2.Combine("Currencies", "CurrenciesBackup")

local DefaultTable = {
	["Tires"] = 500,
	["Candy"] = 0,
	["Presents"] = 0,
	["Chocolate"] = 0,
}

game:GetService("Players").PlayerAdded:Connect(function(Player)
	local DataStore = DataStore2("Currencies", Player)

	local DataTable = DataStore:GetTable(DefaultTable)

	local Data = Instance.new("BinaryStringValue")
	Data.Name = "Currencies"
	Data.Parent = Player

	for DataType, Value in pairs(DataTable) do
		Data:SetAttribute(DataType, Value)
	end

	for DataType, Value in pairs(DefaultTable) do
		if not Data:GetAttribute(DataType) then
			Data:SetAttribute(DataType, Value)
		end
	end

	Data.AttributeChanged:Connect(function()
		local DataToSave = {}

		for Map, Value in pairs(Data:GetAttributes()) do
			DataToSave[Map] = Value
		end
		DataStore:Set(DataToSave)
	end)
end)

This saves just fine for me when teleporting back, and you can treat it like normal leader stats.

1 Like

Two months have passed since then and the problem is still not solved.

The previous code had a lot of compassion for cheats, so I tried to change some things, but of course data is lost during teleportation.

I don’t have perfect knowledge of DataStore2 yet, and the code is still in the prototyping stage, so I’m assuming that the code is bloated in this way and that this problem is related to that. (Still, a lot of things don’t add up.)

I have the data separated by folder, do you not do that over there? (Separate by Currency, separate by tower, etc.)

DataStore2 has a lot of issues related to multiplayer, that I am converting my live experience to ProfileService with a conversion process. Perhaps using ProfileService would be a much better option.

Also, ProfileService is a lot more versiltile, meaning that you can access data from the player even if they are offline.

I see, I heard something very interesting.
is it possible to perfectly transfer the data already stored in DataStore2 to ProfileService?

I do believe the bloat is an issue, you make a seperate datastore for soooooo many things, tables do exist to eliminate this like you could theoretically just have local PlayerData = DataStore2(“PlayerData”, player) and then set up a huge table with all the entities

I can’t verify this but I believe the bloat could impact saving times, I also encountered this other issue and made a remark in a separate post:

I recall having a similar issue where I implemented ds2 with a game where mass teleporting was involved and there were issues with potential dataloss due to how ds2 saves (or atleast I believe it to be so) someone may buy an item and later teleport and a mass queue would result from teleporting with other players and it just could not save in time for the player to then join the teleported server with the same inventory etc. as when he joined the initial server lobby and when leaving it would save the old data instead.

you also say this:

This is a Tower Defense game, and when you finish defeating a boss, you get an Exit button (back to the lobby), and when you press it, all the XP and data you gained in that server will be lost, and you will be returned to the lobby.

Does the issue occur without the SaveAll functionality (I’m assuming thats why you decided to add it, to try and fix the issue)?, Ultimately you need to optimize into a singular table or something, and utilize saveasync (part of the ds2 api, I can provide sample code for ease) to check if data successfully saved, then send them off to the lobby

and as far as this goes @ImKinaco you should avoid be avoid physical objects and folders and you should be handling the information within scripts and while it is entirely up to you to do this and it may be past the point of return, its not a desirable habit, the more advanced you get in coding.

There are many things that just don’t add up, and of course I am well aware that this bloated code needs to be fixed.

Why is this happening when the value is supposed to be saved each time it changes?

Why does it work perfectly when they press the Leave button on Roblox (the data is not saved when they press the button to return to the lobby provided by the game)?

And yes, the same problem occurs without SaveAll

Edit: Is there a way to read player data from other scripts without using physical values or folders? (e.g. what towers they own. or number of XP)

DS2 natively does not save until the player leaves, instead it has user data in a local cache to reduce significant getter requests. This cache is made upon the first get() which I assume is in a playeradded listening function you have.

again my ultimate solution here is:

  1. Set up a singular table as your only datastore

  2. Utilize saveasync() functionality when letting the player leave via your exit button (basically will make a success bool where if successful save then proceed to return to lobby else while loop until success with wait(1) to prevent infinite unhindered loop potential (which shouldn’t occur but always safe to yield)

Is there a way to read player data from other scripts without using physical values or folders?

Typically you would handle all variables within local variables of scripts, whenever you need to update them you would change them within the own script or communicate to other scripts the change.

It may be too much of a hassle for you at this stage to deal with I do not want to put this burden on you, but just to make you aware of a bad habit for later projects.

That’s a very satisfying answer. Thank you so much.
And I should be a little more knowledgeable about data too.

If you don’t mind, may I take a look at the saveasync sample code you mentioned earlier?

You would, in your case, make something like this:

local success, errorMessage = pcall(function()
	InventoryStore:SaveAsync()
end)
	if not success then
		print(errorMessage)
repeat
wait(1)
success, errorMessage = pcall(function()
	InventoryStore:SaveAsync()
end)
until success


	end

--let them leave after passing through the if block

something like this should work, just fix indentation and the datastore is a sample name.

I’ve also seen code where it has a number of retries before ultimately breaking the repeat loop or equivalent loop within setasync which is regular datastore functionality (both pretty much identical) its entirely your call. You might also consider breaking the loop if the player leaves during this. It is recommended @ImKinaco

2 Likes

Please excuse my repeated attempts to contact you.

I have stored data where the original data (for example, boolean, num value and others) is quite complex, can I store it as one table and read data from it at any time without any problems?

The game is already in public beta and we want to improve it without losing the players’ data.

there would be no issues having an ultimate parent table holding the entities (you say they are complex but they are actually simple at least from reading the sample code provided and their associated table data)

--sample
PlayerData = {

Achievements={
--empty or not
},

XP=0,
--etc
}

One thing that came on my mind was if you wanted to convert or migrate peoples data, handle converting in the lobby so you don’t have to call combine on so many datastores within the main game area

1 Like

The problem has finally been resolved also the lag is much reduced. Thank you so much!

1 Like