How can I better optimize datastores?

DataStoreHelp.rbxl (35.8 KB)

My code is intended to save and load values to a datastore such as Coins, Kills, Deaths, Chat Prefixes, Donations, etc. While it works, I believe there would be a better way to optimize it, but I do not know how.

Any feedback or help would be greatly appreciated! This is my first large-scale project that has needed datastores, so I’m not too great with them.

Datastore Script (In ServerScriptService)

local DataStoreService = game:GetService('DataStoreService')

local playerKillsValue = DataStoreService:GetDataStore('playerLifeTimeKills')
local playerDeathsValue = DataStoreService:GetDataStore('playerLifeTimeDeaths')
local playerCoinsValue = DataStoreService:GetDataStore('playerCoins')
local playerPrefixValue = DataStoreService:GetDataStore('playerPrefix')
local playerDonationAmount = DataStoreService:GetDataStore('playerDonations')

game.Players.PlayerAdded:Connect(function(player)
	local Kills = Instance.new('NumberValue')
	Kills.Name = 'Kills'
	Kills.Parent = player:WaitForChild('playerVariables')
	
	local Deaths = Instance.new('NumberValue')
	Deaths.Name = 'Deaths'
	Deaths.Parent = player:WaitForChild('playerVariables')
	
	local Coins = Instance.new('NumberValue')
	Coins.Name = 'Coins'
	Coins.Parent = player:WaitForChild('playerVariables')
	
	local Prefix = Instance.new('StringValue')
	Prefix.Name = 'Prefix'
	Prefix.Parent = player:WaitForChild('playerVariables')
	
	local Donations = Instance.new('NumberValue')
	Donations.Name = 'Donations'
	Donations.Parent = player:WaitForChild('playerVariables')
	

	local data
	local data2
	local data3
	local data4
	local data5
	local success, failure = pcall(function()
		data = playerKillsValue:GetAsync(player.UserId.. ":Kills")
		data2 = playerDeathsValue:GetAsync(player.UserId.. ":Deaths")
		data3 = playerCoinsValue:GetAsync(player.UserId.. ":Coins")
		data4 = playerPrefixValue:GetAsync(player.UserId.. ":Prefix")
		data5 = playerDonationAmount:GetAsync(player.UserId.. ":Donations")

	end)

	if success then
		print('Sucess loading data values for ' .. player.Name)
		Kills.Value = data
		Deaths.Value = data2
		Coins.Value = data3
		Prefix.Value = 'None'
		Prefix.Value = data4
		Donations.Value = data5

	else
		print('Error retriving data for ' .. player.Name)
		warn(failure)
	end

end)

game.Players.PlayerRemoving:Connect(function(player)
	local success, failure = pcall(function()
		playerKillsValue:SetAsync(player.UserId.. ':Kills', player:WaitForChild('playerVariables'):WaitForChild('Kills').Value)
		playerDeathsValue:SetAsync(player.UserId.. ':Deaths', player:WaitForChild('playerVariables'):WaitForChild('Deaths').Value)
		playerCoinsValue:SetAsync(player.UserId.. ':Coins', player:WaitForChild('playerVariables'):WaitForChild('Coins').Value)
		playerPrefixValue:SetAsync(player.UserId.. ':Prefix', player:WaitForChild('playerVariables'):WaitForChild('Prefix').Value)
		playerDonationAmount:SetAsync(player.UserId.. ':Donations', player:WaitForChild('playerVariables'):WaitForChild('Donations').Value)

	end)
	if success then
		print("Saved data values for " .. player.Name)
	else
		print('data values for ' .. player.Name .. ' were not saved sucessfully')
		warn(failure)
	end

end)

Having 5 variables to store 5 stats is not good. You should do something like this instead.

local DS = game:GetService('DataStoreService')
local HS = game:GetService('HttpService')
local Store = DS:GetDataStore('Values')

local Values = {
	{Name = 'stat1',Type = 'IntValue'};
	{Name = 'stat2',Type = 'IntValue'};
	{Name = 'stat3',Type = 'IntValue'};
}
-- If you don't know what an IntValue is, it basically holds a number without decimals (integer)

local function LoadData(Plr:Player)
	repeat task.wait() until Plr

	local Folder = Instance.new('Folder',Plr)
	Folder.Name = 'leaderstats'

	for _, Value in Values do
		Instance.new(Value.Type,Folder).Name = Value.Name
	end

	local Data
	local Loaded,Error = pcall(function()
		Data = Store:GetAsync(Plr.UserId)
	end)

	if Data and Loaded then
		local DecodedData = HS:JSONDecode(Data)
		for Name, Value in DecodedData do
			Folder[Name].Value = Value
		end
	elseif not Loaded and Error then
		warn('Could not load data for player ',Plr.Name,'! Error: ',Error)
	end
end

local function SaveData(Plr:Player)
	if Plr then
		local Folder = Plr.leaderstats

		local StatsToSave = {}

		for _, Value in Folder:GetChildren() do
			StatsToSave[Value.Name] = Value.Value
		end

		local Data
		local Loaded,Error = pcall(function()
			Data = Store:SetAsync(Plr.UserId,HS:JSONEncode(StatsToSave))
		end)

		if not Loaded and Error then
			warn('Could not save data for player ',Plr.Name,'! Error: ',Error)
		end
	end
end

game.Players.PlayerAdded:Connect(LoadData)
game.Players.PlayerRemoving:Connect(SaveData)

Edit : Oh also, you should probably save this as a .txt file in your downloads so you don’t have to go from 1 place to another.

2 Likes

Thank you so much for this! This is definitely better than before! As I said, I’m new to DataStores, so if you don’t mind, could you explain how this saves more space over the approach I was taking before?

Edit: Not just how it saves space, but how it’s better in general

The way you did it before is setting 5 values into a datastore just for 1 player (Which is probably bad). But only setting 1 value better, and it is also easier to modify, like you don’t have to add/remove a variable everytime you need a new leaderstat.

That makes a lot of sense, thank you so very much!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.