Efficient Datastore

Hello, I am an intermediate programmer on Roblox Studio and I would like to share a script I developed that saves player data efficiently. I thought of the question: How can I save player data using datastores efficiently? and I thought of this amazing system. Right now, the system only prevents duplicate saves but there will be more in the future. If you have any suggestions to improve this script, let me know in the comments below.

HOW TO USE:

Copy the script and put it in the Server Script Service of your game.

The script’s URL: Efficient Datastore v1.0 - Roblox

The Script:

-- This is one of the best kinds of datastores to use because it find the most efficient way to read/write data in your game!

--If the datastore does not work, go into settings, save your game to roblox, go to settings again, click on security, and enable api services.
--This enables Datastores

local Leaderstat_settings = { --To add more, make a new line, name it data#, and assign a name to the data like shown below and.... let the magic happen!
	data1 = "Gold";
	data2 = "Diamonds";
}

local currentlyLoaded = {}
local currenlySaved = {}

local dds = game:GetService("DataStoreService"):GetDataStore("DDS_NAME_HERE") -- You can change DDS_NAME_HERE if you want but you do not have to

local function getData(plr)
	
	local successfully_loaded_data = {}

	for i,v in pairs(Leaderstat_settings) do
		local saved_data = dds:GetAsync(plr.UserId.. "-".. v)

		if saved_data then
			table.insert(successfully_loaded_data, saved_data)
		else
			return
		end
	end
	if successfully_loaded_data == nil then
		return
	else
		currenlySaved = successfully_loaded_data
		return successfully_loaded_data
	end
end

local function saveData(plr)
	pcall(function()
		for i,v in pairs(plr.leaderstats:GetChildren()) do
			wait(.05)
			dds:SetAsync(plr.UserId.."-"..v.Name, v.Value)
		end
	end)
end



game.Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder", player)
	leaderstats.Name = "leaderstats"

	for i,v in pairs(Leaderstat_settings) do
		local newDataPoint = Instance.new("IntValue", leaderstats)
		newDataPoint.Name = v
	end
	
	local loaded_data = getData(player)
	
	if loaded_data then
		for i,v in pairs(loaded_data) do
			player.leaderstats:GetChildren()[i].Value = loaded_data[i]
		end
	end
end)

game.Players.PlayerRemoving:Connect(function(plr)
	for i,v in pairs(plr.leaderstats:GetChildren()) do
		table.insert(currentlyLoaded, plr.leaderstats[v.Name].Value)
	end
	
	wait()
	local numberOfLeaderstatsValues = #Leaderstat_settings
	local numberOfCongruentValues = 0
	
	for i,v in pairs(currenlySaved) do
		for x,c in pairs(currentlyLoaded) do
			if v == c then
				numberOfCongruentValues += 1
			end
			if numberOfCongruentValues >= numberOfLeaderstatsValues then
				warn("Saved Datastore Bandwidth by preventing a duplicate save!")
				return
			else
				saveData(plr)
			end
		end
	end
end)
1 Like

Firstly, this post belongs in #resources.

Secondly, I don’t think this is useful for anything. You cannot save duplicates. The duplicates or the previous data saves are either garbage collected or the most recent data save is chosen.

  • You can save a table that contains the data values (Gold and Diamonds) without looping through. I think your code has some useless stuff in it and you could definitely optimize it.

By the way, I am not trying to make you look bad or anything, I get you’re an intermediate scripter and I have all my respect for you for coding all of this. I just wanted to share my thoughts.

4 Likes

I don’t think you should be calling GetAsync in a loop with no yielding. Let alone at all.

Instead of getting two datasaves, Gold and Diamonds, just put them in a table and save them under one datastore. You can cut data loading and saving times in half with this.

1 Like