DataStores for Dummies

Welcome to this tutorial made by me !

DataStore are used in various games like Jailbreak or Adopt me to save players data ! Anyone who knows DataStore is definitely not a beginner and can be proud of himself.

To access DataStores you’ll need to enable Studio Access to Roblox Api :

Now the fun can start

local DataStoreService = game:GetService("DataStoreService") -- Access DataStoreService
local database = DataStoreService:GetDataStore("database") -- Create a new database if its unexistent otherwise access it

Since it’s a tutorial for dummies we’ll only cover two of the most important function :
:GetAsync() and :SetAsync()

:GetAsync() is used to get data from a database using a scope (like player’s user id)
:SetAsync() is used to put data by taking two arguments : the scope (player user id, don’t use player’s username to save data as it can be changed for 1000 robux) and the data (numbers, table…).

Here’s an illustrated example of what a coin datastore looks like:

Let’s now use our knowledge for example the coin data of a player leaderboard (I’m assuming you know how to make a leaderboard).

local DataStoreService = game:GetService("DataStoreService")
local coinDatabase = DataStoreService:GetDataStore("coinDatabase") -- Make the coin database

local players = game:GetService("Players")

-- If a player is added
players.PlayerAdded:Connect(function(player)

	-- Make the leaderboard
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	-- Make the coin value Inside of the leaderboard
	local coins = Instance.new("IntValue")
	coins.Parent = player

	-- Try getting the data from the database
	local data = coinDatabase:GetAsync(player.UserId)

	-- If data found then puts it in coins, otherwise uses default value
	if data then
		coins.Value = data
	else
		coins.Value = 30
	else
end)

-- If the player is leaving
players.PlayerRemoving:Connect(function(player)
	coinDatabase:SetAsync(player.UserId, player.leaderstats.Coins.Value)
end)

TADAAA, we got our server script ! It works most of the time. Now you’re probably asking : fancym what do you mean most of the time ? And yes , it will only work most of the time because the api is unreliable and can fail to load or save data. But we can maximize our chance of not getting this error with this technique :

Instead of just getting or saving the data we can make an attempt system that will keep trying until the script did 5 attempts or it successfully loaded or saved the data.

Like this :

local DataStoreService = game:GetService("DataStoreService")
local coinDatabase = DataStoreService:GetDataStore("coinDatabase") -- Make the coin database

local players = game:GetService("Players")

-- If a player is added
players.PlayerAdded:Connect(function(player)

	-- Leaderboard part bla bla bla

	-- Keep trying to get the data until 5 attempts or success
	local attempt = 0
	repeat
		local success, error = pcall(function()
			local data = coinDatabase:GetAsync(player.UserId)

			if data then
				player.leaderstats.Coins.Value = data
			else
				player.leaderstats.Coins.Value = 30
			end
		end)
		attempt += 1
		task.wait()
	until success or attempt == 5
end)

-- If the player is leaving
players.PlayerRemoving:Connect(function(player)
	-- Keep trying to save the data until 5 attempts or success
	local attempt = 0
	repeat
		local success, error = pcall(function()
			coinDatabase:SetAsync(player.UserId, player.leaderstats.Coins.Value)
		end)
		attempt += 1
		task.wait()
	until success or attempt == 5
end)

There you go ! Now you can save data as much as you want ! You’re now a pro : )

9 Likes

Just wanted to say this is a nice tutorial, an improved version of mine. I should’ve mentioned pcall retry logic aswell:

what I would recommend though to add is after the few retries for getasync that you actually teleport the player into the game again. Just incase data has still FAILED to load after 5 retries:

local attempt = 0
	repeat
if Attempt == 5 then
TeleportService:Teleport(player) -- Cant remember the exact syntax
		local success, error = pcall(function()
			local data = coinDatabase:GetAsync(player.UserId)

			if data then
				player.leaderstats.Coins.Value = data
			else
				player.leaderstats.Coins.Value = 30
			end
		end)
		attempt += 1
		task.wait(1) -- Added a longer yield because data store limits
	until success
4 Likes

Thanks. Also a common practice I’ve seen was to kick the player asking them to rejoin *(I think this is the best way to do it since hackers may uses lag to bypass BanAsync or the ban system you made with DataStores).

player:Kick("Please rejoin the game")

2 Likes

Yeah kicking is also a good idea but it may annoy players if let’s say, they’re trying to join their friends. Just teleporting them back in ensures they don’t leave the game and go to do something else.

Also I think there should be a few more retries for setasync since saving data is the most important part.

2 Likes

Really good tutorial its very simple which makes it super helpful

2 Likes