Before getting started
Welcome to Part 3 of our roblox shop gui tutorial ! In the previous parts, we built the UI and scripted the purchase logic. However, there is one major problem: When a player leaves the game, they lose their money and items.
To fix this, we need Data Persistence . In this guide, we will implement a robust Roblox DataStore script that saves the player’s leaderstats (Cash) and their inventory (Tools) so everything loads back up when they rejoin.
This is the fully functional shop you’ll have at the end of the tutorial, with images / backgrounds fully customizable, and with DataStores & buying with Robux and in-game currency.
If you want to skip straight to having everything working, the great news is I already made a plugin to do that, so you can just download the free plugin here
If you want to build the Shop from scratch, keep reading…
Part 3: Saving Currency & Items (DataStore Persistence)
Step 1: Enabling API Services
Before writing a single line of code, we must tell Roblox Studio that it is allowed to access the database. By default, this is turned off for security.
-
Open Roblox Studio.
-
Go to the Home tab at the top and click Game Settings .
-
Go to the Security tab.
-
Toggle “Enable Studio Access to API Services” to ON .
-
Click Save.
Without this step, your roblox shop gui will throw errors whenever you try to save data while testing in Studio.
Step 2: Understanding Serialization (Saving Objects)
Here is the technical challenge: You cannot save a Tool (a 3D object) into a DataStore. DataStores only understand numbers and text (Strings).
To solve this, we use a process called Serialization .
-
Saving: We don’t save the Sword object. We look at the player’s inventory, see they have a “CoolSword”, and save the word “CoolSword” into a list.
-
Loading: When the player joins, we read the list. If we see the word “CoolSword”, the server goes to ReplicatedStorage, finds the original Tool, clones it, and gives it to the player.
Step 3: The DataStore Script
We are going to modify the LeaderstatsScript we created in Part 2. Go to ServerScriptService and open that script. Delete what is there and replace it with this complete Data Handler.
We use pcall (Protected Call) in this script because internet connections can fluctuate. If the Roblox database is momentarily down, pcall prevents your entire game script from crashing.
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- We create a specific "Key" for our datastore.
-- If you ever want to wipe everyone's data, just change this name (e.g. "ShopData_V2")
local myDataStore = DataStoreService:GetDataStore("ShopData_V1")
-- 1. Loading Data when Player Joins
Players.PlayerAdded:Connect(function(player)
-- Setup Leaderstats (Visual Money)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local cash = Instance.new("IntValue")
cash.Name = "Cash"
cash.Parent = leaderstats
-- Setup Inventory Data Logic
local playerUserId = "Player_" .. player.UserId
local data
-- Fetch data safely
local success, err = pcall(function()
data = myDataStore:GetAsync(playerUserId)
end)
if success and data then
-- A. Load Currency
cash.Value = data.Cash
-- B. Load Items
-- We loop through the saved LIST of names, and find the matching tool
if data.Items then
for _, itemName in ipairs(data.Items) do
local toolTemplate = ReplicatedStorage:FindFirstChild(itemName)
if toolTemplate then
local newTool = toolTemplate:Clone()
newTool.Parent = player.Backpack
-- Also add to StarterGear so they keep it if they die
local gear = toolTemplate:Clone()
gear.Parent = player.StarterGear
end
end
end
print("Data loaded successfully!")
else
-- New player (or data failed), give starting cash
cash.Value = 100
warn("No data found or error loading.")
end
end)
-- 2. Saving Data when Player Leaves
Players.PlayerRemoving:Connect(function(player)
local playerUserId = "Player_" .. player.UserId
-- Create a table to hold everything we want to save
local dataToSave = {
Cash = 0,
Items = {} -- A blank list to fill with tool names
}
-- A. Save Currency
if player:FindFirstChild("leaderstats") then
dataToSave.Cash = player.leaderstats.Cash.Value
end
-- B. Save Items (Serialization)
-- We look at the player's Backpack to see what they are holding
for _, item in ipairs(player.Backpack:GetChildren()) do
if item:IsA("Tool") then
table.insert(dataToSave.Items, item.Name)
end
end
-- Save safely
local success, err = pcall(function()
myDataStore:SetAsync(playerUserId, dataToSave)
end)
if success then
print("Data saved!")
else
warn("Failed to save data: " .. err)
end
end)
-- 3. Safety Check: Save on Server Shutdown
-- If the server crashes or shuts down for updates, PlayerRemoving might not trigger.
-- This ensures we loop through all remaining players and force-save them.
game:BindToClose(function()
for _, player in ipairs(Players:GetPlayers()) do
-- Trigger the save logic manually here (simplified for tutorial brevity)
-- In a real game, you would abstract the saving logic into a shared function.
print("Saving data for " .. player.Name .. " due to server shutdown.")
end
task.wait(2) -- Give the server a moment to finish saving requests
end)
Step 4: Testing Your DataStore
Testing a roblox shop gui example with data persistence requires a specific workflow because Studio shuts down faster than data can save sometimes.
-
Play the game in Studio.
-
Open your Shop and buy the “CoolSword” (from Part 2).
-
Stop the game.
-
Play the game again.
If you see the Sword in your hotbar and your Cash is lower than 100, congratulations! You have successfully created a persistent economy system.
You now have a complete loop: A UI to interact with, a server to handle purchases, and a DataStore to remember it all. This is the foundation of every major game on the platform.