Use DataStore to save and retrieve core data, such as the player’s level, EXP, and current gold. This allows you to maintain the player’s progress over time and develop games with growth mechanics, such as in RPGs.
How to Use
Supported Data Types
Data Type
Supported O/X
number
O
string
O
bool
O
table
O
object
Not supported.
Functions
Not supported.
Default Structure
Use the GetDataStore function of DataStoreService to retrieve DataStore objects with a designated name. You can save or retrieve data using a key-value format within the DataStore object.
Key: Unique name that identifies data (e.g. PlayerGold)
Value: Data to be saved (e.g. 1,000)
Function
Description
GetDataStore(name)
Retrieve Datastore object that corresponds to the name
GetAsync(key)
Retrieve data that corresponds to the key in the Datastore object
SetAsync(key, value)
Save (overwrite) data in the key in the Datastore object
Data Store Retrieval
local DataStoreService = game:GetService("DataStoreService")
local GoldStore = DataStoreService:GetDataStore("PlayerGold")
Saving
local function SaveData(player)
local success, errorMessage = pcall(function()
local saveValue = 1
-- Key : PlayerName / Value : SaveValue
GoldStore:SetAsync(player.UserId, saveValue)
end)
if not success then
print("errorMessage : ", errorMessage)
end
end
Retrieving
local function LoadData(player)
local success, errorMessageOrLoadValue = pcall(function()
-- Key : PlayerName
return GoldStore:GetAsync(player.UserId)
end)
if not success then
print("errorMessage : ", errorMessageOrLoadValue)
else
local loadValue = errorMessageOrLoadValue
print(player.Name, "Load PlayerGold : ", loadValue)
end
end
Full Code Example
The following code retrieves data stored on the server when a player enters the game. If no saved value is found, the initial value is set, and this value is assigned as the player’s Attribute.
When the save function is called, the current value of the Attribute is saved to the server.
DataManager = {}
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
-- Definition of various data types that are saved or retrieved
local PlayerData =
{
{ Name = "PlayerGold", InitValue = 0, Store = nil },
}
for i = 1, #PlayerData do
PlayerData[i].Store = DataStoreService:GetDataStore(PlayerData[i].Name)
end
--------------------------------------------------------
-- Saves the current value to the server
function DataManager:SavePlayerData(player)
repeat wait() until player:GetAttribute("IsDataLoaded")
print(player, "> SavePlayerData")
local text = ">>>> Save : "
for i = 1, #PlayerData do
local playerData = PlayerData[i]
local store = playerData.Store
local success, errorMessageOrLoadValue = pcall(function()
-- Reads the player's Attribute value and saves it to the server.
local currentValue = player:GetAttribute(playerData.Name)
store:SetAsync(player.UserId, currentValue)
return currentValue
end)
if not success then
text = text .. "errorMessage : " .. errorMessageOrLoadValue
else
local loadValue = errorMessageOrLoadValue
if i > 1 then
text = text .. ", "
end
text = text .. player.Name .. " / Save " .. playerData.Name .. " : " .. tostring(loadValue)
end
end
print(player, text)
end
-- Automatically saves when the player exits the game.
Players.PlayerRemoving:Connect(function(player) DataManager:SavePlayerData(player) end)
--------------------------------------------------------
-- Retrieves the value saved in the server.
function DataManager:LoadPlayerData(player)
print(player, "> LoadPlayerData")
local text = ">>>> Load : "
for i = 1, #PlayerData do
local playerData = PlayerData[i]
local store = playerData.Store
local success, errorMessageOrLoadValue = pcall(function()
return store:GetAsync(player.UserId)
end)
if not success then
text = text .. "errorMessage : " .. errorMessageOrLoadValue
else
local loadValue = errorMessageOrLoadValue
-- If no saved value exists, the initial value (InitValue) is set and saved to the server.
if loadValue == nil then
loadValue = playerData.InitValue
store:SetAsync(player.UserId, loadValue)
end
-- The retrieved value is set as the player's Attribute
player:SetAttribute(playerData.Name, loadValue)
if i > 1 then
text = text .. ", "
end
text = text .. player.Name .. " / Load " .. playerData.Name .. " : " .. tostring(loadValue)
end
end
player:SetAttribute("IsDataLoaded", true)
print(player, text)
end
--------------------------------------------------------
-- Retrieves data when the player enters the game.
local function LoadPlayerDataWhenEnter(player)
local function onAddCharacter(character)
print(player.Name .. " LoadPlayerDataWhenEnter")
DataManager:LoadPlayerData(player)
end
player.CharacterAdded:Connect(onAddCharacter)
end
Players.PlayerAdded:Connect(LoadPlayerDataWhenEnter)
--------------------------------------------------------
-- Example of data retrieval
local function LoadExample(player)
DataManager:LoadPlayerData(player)
end
-- Example of saving data
local function SaveExample(player)
-- Example code that changes the value prior to saving
for i = 1, #PlayerData do
local playerData = PlayerData[i]
local currentValue = player:GetAttribute(playerData.Name)
if currentValue ~= nil then
local newValue = currentValue + 1
player:SetAttribute(playerData.Name, newValue)
end
end
DataManager:SavePlayerData(player)
end
LoadPlayerDataWhenEnter(player)
Load when the player logs in to the game
DataManager:LoadPlayerData(player)
Retrieves player data saved in the server (GetAsync)
If no saved value exists, the initial value (InitValue) is set and saved to the server.
The retrieved value is set as the player’s Attribute
DataManager:SavePlayerData(player)
Reads the player’s Attribute value and saves it to the server (SetAsync)
Automatically saves when the player exits the game through the PlayerRemoving event.
Usage Example
When saving or retrieving data from DataStore, you can manage both individual user data and global game data depending on how the key value is structured.
This approach allows you to save and retrieve game data across all areas, such as leaderboards, event progress, server settings, etc.
Difference Between Actions in Published and Test Environments
After publishing, data is saved and retrieved on the live server in mobile environments. However, in studio test environments, data is temporarily stored locally. When the studio session ends, this local data is automatically deleted.
Important Notes
If the player starts playing the game before the data is fully loaded, an error may occur. To prevent this, display a loading UI until the data has finished loading.
Design the data to be saved in a structure that is as compact and simple as possible.
Excessive requests can lead to data save failures, so avoid making repeated saves within a short time frame.
API retrieval cannot exceed 150 requests per minute. Exceeding this limit may result in restrictions on the server.
If the game unexpectedly ends or there is a server collision, data may be lost. To prevent this, ensure that data is saved periodically.
Saving and retrieval may fail, so use pcall to prevent errors and add a retry logic.
For example, if the key is set up as “RaceGameLeaderBoard” instead of “,” you can manage ranking information stored on the server rather than data specific to an individual player.