I Am Having An Issue When It Comes To Sorting Multiple Data For DataStores

Hello People! I Have Been Trying To Make A DataStore For Player Stats, (Like Speed, Power, Stamina, Or Their Level As IntValues Within A Folder Of The Player’s Backpack (Note: I Am New To DataStore Related Stuff)) And To Be Honest, I Have Gotten Pretty Close. The Only Issue I Am Dealing With, Is That When The Values Are Loaded, They Are Stored In The Wrong Order, Causing Specific Stats To Not Work As Intended. As Of Now, I Have Tried A Few Things, Mainly Inserting Them Into A Table Before Storing Them, or Even Using, “:GetSortedAsync()”, “GetOrderedDataStore” And What Not, But These Have Yet To Work. (Unless I Am A Noob, And Is The Reason That’s Why) For Those Who Would Like To Help Out, I Have The Code Listed Below, And If You Guys Know The Solution, I’d Really Like To Know, It Would Really Help Me Out, Thank You! :grinning_face_with_smiling_eyes:

--Basic Variables--
local DataStoreService = game:GetService("DataStoreService")
local LevelData = DataStoreService:GetOrderedDataStore("LevelData")
--Main Function--
game.Players.PlayerAdded:Connect(function(Player)
	wait(5)
	local Backpack = Player:WaitForChild("Backpack")
	local PlayerStats = Backpack:FindFirstChild("PlayerStats") and Backpack:WaitForChild("PlayerStats")
	local LevelStats = Backpack:FindFirstChild("LevelStats") and Backpack:WaitForChild("LevelStats")
	local Data
	for I,V in pairs(PlayerStats:GetDescendants()) do
		if V ~= nil then
			if V:IsA("IntValue") and V:FindFirstAncestorWhichIsA("Folder").Name == LevelStats.Name or V:FindFirstAncestorWhichIsA("Folder").Name == PlayerStats.Name then
				local Success,ErrorMessage = pcall(function()
					Data = LevelData:GetAsync(Player.UserId,V.Value)
					wait()
				end)
				if Success then
					V.Value = Data
				else
					print("There Was An Error Saving Player Data")
					warn(ErrorMessage)
				end
			end
		end
	end
	for I,V in pairs(LevelStats:GetDescendants()) do
		if V ~= nil then
			if V:IsA("IntValue") and V:FindFirstAncestorWhichIsA("Folder").Name == LevelStats.Name or V:FindFirstAncestorWhichIsA("Folder").Name == PlayerStats.Name then
				local Success,ErrorMessage = pcall(function()
					Data = LevelData:GetAsync(Player.UserId,V.Value)
					wait()
				end)
				if Success then
					V.Value = Data
				else
					print("There Was An Error Saving Player Data")
					warn(ErrorMessage)
				end
			end
		end
	end
end)
------------------------------------------------------
game.Players.PlayerRemoving:Connect(function(Player)
	wait(5)
	local Backpack = Player:WaitForChild("Backpack")
	local PlayerStats = Backpack:FindFirstChild("PlayerStats") and Backpack:WaitForChild("PlayerStats")
	local LevelStats = Backpack:FindFirstChild("LevelStats") and Backpack:WaitForChild("LevelStats")
	for I,V in pairs(PlayerStats:GetDescendants()) do
		if V ~= nil then
			if V:IsA("IntValue") and V:FindFirstAncestorWhichIsA("Folder").Name == LevelStats.Name or V:FindFirstAncestorWhichIsA("Folder").Name == PlayerStats.Name then
				local Success,ErrorMessage = pcall(function()
					LevelData:GetAsync(Player.UserId,V.Value)
					wait()
				end)
				if Success then
					print("Successfully Saved Data!")
				else
					print("There Was An Error Saving Player Data")
					warn(ErrorMessage)
				end
			end
		end
	end
	for I,V in pairs(LevelStats:GetDescendants()) do
		if V ~= nil then
			if V:IsA("IntValue") and V:FindFirstAncestorWhichIsA("Folder").Name == LevelStats.Name or V:FindFirstAncestorWhichIsA("Folder").Name == PlayerStats.Name then
				local Success,ErrorMessage = pcall(function()
					LevelData:GetAsync(Player.UserId,V.Value)
					wait()
				end)
				if Success then
					print("Successfully Saved Data!")
				else
					print("There Was An Error Saving Player Data")
					warn(ErrorMessage)
				end
			end
		end
	end
end)

Here Is The Script, I Hope This Can Help In Someway As A Sort Of Reference (The Stats Are IntValues Within Specific Folders Of The Player’s Backpack) :slight_smile:

When you do a load you use GetAsync
And
When you do a save you do GetAsync
is that intended?

why your using GetAsync on PlayerRemoving(saving the data)?

When you save you should use Datastore:SetAsync, as it sets a value inside a Datastore to something,
As when you are loading stuff you should use Datastore:GetAsync, as it’s getting the information from the datastore,

Check out this article about datastores

You can check out this tutorial

These might help you understand it better

It was, but I don’t know if that’s the correct method or not. I am pretty noobish when it comes to DataStore.

I am using it on here since I thought that PlayerRemoving(), should still require :GetAsync. If it’s wrong I am sorry, I’ve still got a long way to go.

I’ve Tried The Tutorial And I Am Coming Up With An Error.

Can you send the script so i can see whats going on?

sure thing!

--Basic Variables--
local DataStoreService = game:GetService("DataStoreService")
local LevelData = DataStoreService:GetOrderedDataStore("MyDataStore")
--Sub Function--
local function SaveData(Player)
	local TableToSaveData = {
		Player.Backpack.LevelStats.CurrentLevel.Value;
		Player.Backpack.LevelStats.CurrentLevel.RequiredExp.Value;
		Player.Backpack.LevelStats.StatAwards.Value;
		Player.Backpack.LevelStats.StatsExp.Value;
		Player.Backpack.PlayerStats.AvailableStats.Value;
		Player.Backpack.PlayerStats.Defense.Value;
		Player.Backpack.PlayerStats.FightingSpirit.Value;
		Player.Backpack.PlayerStats.FightingSpirit.AddOn.Value;
		Player.Backpack.PlayerStats.FightingSpirit.Max.Value;
		Player.Backpack.PlayerStats.Speed.Value;
		Player.Backpack.PlayerStats.Speed.PunchSpeed.Value;
		Player.Backpack.PlayerStats.Stamina.Value;
		Player.Backpack.PlayerStats.Strength.Value;
		Player.Backpack.PlayerStats.Strength.AddOn.Value;
	}
	local Success,ErrorMessage = pcall(function()
		LevelData:SetAsync(Player.UserId,TableToSaveData)
	end)
	if Success then
		print("Player Data Has Been Saved!")
	else
		print("There Was An Error Saving Data...")
		warn(ErrorMessage)
	end
end
--Main Function--
game.Players.PlayerAdded:Connect(function(Player)
	local Backpack = Player.Backpack
	local LevelStats = Instance.new("Folder")
	local PlayerStats = Instance.new("Folder")
	LevelStats.Name = "LevelStats"
	PlayerStats.Name = "PlayerStats"
	LevelStats.Parent = Backpack
	PlayerStats.Parent = Backpack
	-----------------------------------------------------------
	local CurrentLevel = Instance.new("IntValue")
	local RequiredExp = Instance.new("IntValue")
	local StatAwards = Instance.new("IntValue")
	local StatExp = Instance.new("IntValue")
	-----------------------------------------------------------
	CurrentLevel.Parent = LevelStats
	RequiredExp.Parent = CurrentLevel
	StatAwards.Parent = LevelStats
	StatExp.Parent = LevelStats
	-----------------------------------------------------------
	CurrentLevel.Name = "CurrentLevel"
	RequiredExp.Name = "RequiredExp"
	StatAwards.Name = "StatAwards"
	StatExp.Name = "StatExp"
	-----------------------------------------------------------
	local AvailableStats = Instance.new("IntValue")
	local Defense = Instance.new("IntValue")
	local FightingSpirit = Instance.new("IntValue")
	local FSAddOn = Instance.new("IntValue")
	local MaxFS = Instance.new("IntValue")
	local Speed = Instance.new("IntValue")
	local PunchSpeed = Instance.new("IntValue")
	local Stamina = Instance.new("IntValue")
	local Strength = Instance.new("IntValue")
	local PWRAddOn = Instance.new("IntValue")
	-----------------------------------------------------------
	AvailableStats.Parent = PlayerStats
	Defense.Parent = PlayerStats
	FightingSpirit.Parent = PlayerStats
	FSAddOn.Parent = FightingSpirit
	MaxFS.Parent = FightingSpirit
	Speed.Parent = PlayerStats
	PunchSpeed.Parent = Speed
	Strength.Parent = PlayerStats
	PWRAddOn.Parent = Strength
	-----------------------------------------------------------
	local Data
	local Success, ErrorMessage = pcall(function()
		Data = LevelData:GetAsync(Player.UserId)
	end)
	if Success then
		CurrentLevel.Value = Data[1]
		RequiredExp.Value = Data[2]
		StatAwards.Value = Data[3]
		StatExp.Value = Data[4]
		AvailableStats.Value = Data[5]
		Defense.Value = Data[6]
		FightingSpirit.Value = Data[7]
		FSAddOn.Value = Data[8]
		MaxFS.Value = Data[9]
		Speed.Value = Data[10]
		PunchSpeed.Value = Data[11]
		Stamina.Value = Data[12]
		Strength.Value = Data[13]
		PWRAddOn.Value = Data[14]
	else
		print("Player Has No Data To Save!")
	end
end)
--------------------------------------------------------------------------------
game.Players.PlayerRemoving:Connect(function(Player)
	local Success,ErrorMessage = pcall(function()
		SaveData(Player)
	end)
	if Success then
		print("Player Data Has Been Saved!")
	else
		print("Data Of The Player Failed To Save.")
	end
end)
--------------------------------------------------------------------------------
game:BindToClose(function()
	for Index,Player in pairs(game.Players:GetPlayers()) do
		local Success,ErrorMessage = pcall(function()
			SaveData(Player)
		end)
		if Success then
			print("Data Has Been Saved For The Player!")
		else
			print("Player's Data Failed To Save...")
		end
	end
end)
1 Like

Here’s the final script

--Basic Variables--
local DataStoreService = game:GetService("DataStoreService")
local LevelData = DataStoreService:GetDataStore("MyDataStore2")
--Sub Function--
local function SaveData(Player)
	local TableToSaveData = {
		Player.LevelStats.CurrentLevel.Value,
		Player.LevelStats.CurrentLevel.RequiredExp.Value,
		Player.LevelStats.StatAwards.Value,
		Player.LevelStats.StatExp.Value,
		Player.PlayerStats.AvailableStats.Value,
		Player.PlayerStats.Defense.Value,
		Player.PlayerStats.FightingSpirit.Value,
		Player.PlayerStats.FightingSpirit.FSAddOn.Value,
		Player.PlayerStats.FightingSpirit.MaxFS.Value,
		Player.PlayerStats.Speed.Value,
		Player.PlayerStats.Speed.PunchSpeed.Value,
		Player.PlayerStats.Stamina.Value,
		Player.PlayerStats.Strength.Value,
		Player.PlayerStats.Strength.PWRAddOn.Value,
	}
	local Success,ErrorMessage = pcall(function()
		LevelData:SetAsync(Player.UserId, TableToSaveData)
	end)
	if Success then
		print("Player Data Has Been Saved!")
	else
		print("There Was An Error Saving Data...")
		warn(ErrorMessage)
	end
end
--Main Function--
game.Players.PlayerAdded:Connect(function(Player)
	local LevelStats = Instance.new("Folder")
	local PlayerStats = Instance.new("Folder")
	LevelStats.Name = "LevelStats"
	PlayerStats.Name = "PlayerStats"
	LevelStats.Parent = Player
	PlayerStats.Parent = Player
	-----------------------------------------------------------
	local CurrentLevel = Instance.new("IntValue")
	local RequiredExp = Instance.new("IntValue")
	local StatAwards = Instance.new("IntValue")
	local StatExp = Instance.new("IntValue")
	-----------------------------------------------------------
	CurrentLevel.Name = "CurrentLevel"
	RequiredExp.Name = "RequiredExp"
	StatAwards.Name = "StatAwards"
	StatExp.Name = "StatExp"
	-----------------------------------------------------------
	CurrentLevel.Parent = LevelStats
	RequiredExp.Parent = CurrentLevel
	StatAwards.Parent = LevelStats
	StatExp.Parent = LevelStats
	-----------------------------------------------------------
	local AvailableStats = Instance.new("IntValue")
	local Defense = Instance.new("IntValue")
	local FightingSpirit = Instance.new("IntValue")
	local FSAddOn = Instance.new("IntValue")
	local MaxFS = Instance.new("IntValue")
	local Speed = Instance.new("IntValue")
	local PunchSpeed = Instance.new("IntValue")
	local Stamina = Instance.new("IntValue")
	local Strength = Instance.new("IntValue")
	local PWRAddOn = Instance.new("IntValue")
	-----------------------------------------------------------
	AvailableStats.Name = "AvailableStats"
	Defense.Name = "Defense"
	FightingSpirit.Name = "FightingSpirit"
	FSAddOn.Name = "FSAddOn"
	MaxFS.Name = "MaxFS"
	Speed.Name = "Speed"
	PunchSpeed.Name = "PunchSpeed"
	Stamina.Name = "Stamina"
	Strength.Name = "Strength"
	PWRAddOn.Name = "PWRAddOn"
	-----------------------------------------------------------
	AvailableStats.Parent = PlayerStats
	Defense.Parent = PlayerStats
	FightingSpirit.Parent = PlayerStats
	FSAddOn.Parent = FightingSpirit
	MaxFS.Parent = FightingSpirit
	Speed.Parent = PlayerStats
	PunchSpeed.Parent = Speed
	Strength.Parent = PlayerStats
	Stamina.Parent = PlayerStats
	PWRAddOn.Parent = Strength
	-----------------------------------------------------------
	local Data
	local Success, ErrorMessage = pcall(function()
		Data = LevelData:GetAsync(Player.UserId)
	end)
	if Data then
		CurrentLevel.Value = Data[1]
		RequiredExp.Value = Data[2]
		StatAwards.Value = Data[3]
		StatExp.Value = Data[4]
		AvailableStats.Value = Data[5]
		Defense.Value = Data[6]
		FightingSpirit.Value = Data[7]
		FSAddOn.Value = Data[8]
		MaxFS.Value = Data[9]
		Speed.Value = Data[10]
		PunchSpeed.Value = Data[11]
		Stamina.Value = Data[12]
		Strength.Value = Data[13]
		PWRAddOn.Value = Data[14]
	else
		print("Player Has No Data To Save!")
	end
end)
--------------------------------------------------------------------------------
game.Players.PlayerRemoving:Connect(function(Player)
	local Success,ErrorMessage = pcall(function()
		SaveData(Player)
	end)
	if Success then
		print("Player Data Has Been Saved!")
	else
		print("Data Of The Player Failed To Save.")
		warn(ErrorMessage)
	end
end)
--------------------------------------------------------------------------------
game:BindToClose(function()
	for Index,Player in pairs(game.Players:GetPlayers()) do
		local Success,ErrorMessage = pcall(function()
			SaveData(Player)
		end)
		if Success then
			print("Data Has Been Saved For The Player!")
		else
			print("Player's Data Failed To Save...")
		end
	end
end)

There were alot of misstypes, I had to go to studio to fix it, whenever i ran the game it wouldn’t put anything in the Backpack, so put the folders in player if u don’t mind, you can change if you want.

Another stuff is you forgot to name alot of intValues,
And on the top of the script you called the DataStore an OrderedDataStore, you usually use Ordered ones if you’re making a leaderboard with top 10 players for example, but yeah you can see the difference between your and my edited script and you can kinda see whats different

When you wrote

		CurrentLevel.Value = Data[1]

It couldn’t get anything because you can’t save arrays (tables) inside an OrderedDataStore, so you wanna use normal DataStores

1 Like

I highly recommend using UpdateAsync for saving since it doesn’t completely overwrite a players data like SetAsync does, so it’s much better considering if an error occurs the old data can still be kept where as if some sort of error could occur with SetAsync there could be a potential data wipe for the player

good to know, thanks for the help man, I appreciate it :+1:

Apparently when the player resets, the folders are deleted with it, Is this because of manually loading the character breaks the script?

ahh idk i never had folders deleting in my case

well actually i got it to work, but now rejoining resets it.

Maybe it could be that it doesnt save in studio, try joining a real game changing some stuff and rejoining and see if it saves

I tested it in- game earlier, but I found an error, it says…

does this have something to do with it?

Edit: here’s this too

image

Did you change anything in the script? It worked fine for me lemme test again

there was a person who told me to use UpdateAsync, maybe that was a wrong choice for me

Yeah he said that UpdateAsync is safer than SetAsync because it can wipe data, it is true but the chance of that happening is really low, I never had it happen in my career