Making a Saving System

Hello everyone! Today I am going to tell you how to save and load data for certain players in your game. I will show two examples, one with my DataStoreCache module (Datastore Caching Module) and one with vanilla datastores.

Vanilla Datastores

Make a Script, not a LocalScript or ModuleScript in the ServerScriptService.
download%20(1)
Call it “SaveScript” and then we can start editting it.

Remove the first line (print("Hello, world!")) and then we can get started.
Let’s get the DataStoreService like so:

-- This loads up the DataStoreService so we can use it:
local dataStoreService = game:GetService("DataStoreService")

Now we can use the dataStoreService variable to get the player’s save. Let’s check when a player joins the game.

-- This loads up the DataStoreService so we can use it:
local dataStoreService = game:GetService("DataStoreService")

-- The provided function is called when a player joins.
-- It's one and only argument that's passed is the player that joined.
game.Players.PlayerAdded:Connect(function(plr)
    -- Now we can do whatever we want to load the Player's data.
end)

Okay, it looks good, but there’s one thing I need to put in here. We are going to use the player’s ID because it never changes, even if the player changes their name. It’s the number in the URL of a player’s profile. Let’s look at mine:
https://www.roblox.com/users/161615648/profile
                                                 ^ This is the UserId of the player.

To get the UserId of a player, all you need to do is reference the property:

-- This loads up the DataStoreService so we can use it:
local dataStoreService = game:GetService("DataStoreService")

-- The provided function is called when a player joins.
-- It's one and only argument that's passed is the player that joined.
game.Players.PlayerAdded:Connect(function(plr)
    -- Now we can do whatever we want to load the Player's data.
    local userId = plr.UserId -- The Player's id.
end)

But, we need to convert it to a string. Any guesses on how to do this?

If you guessed tostring, then you’re correct! Let’s convert the Player’s UserId to a string.

-- This loads up the DataStoreService so we can use it:
local dataStoreService = game:GetService("DataStoreService")

-- The provided function is called when a player joins.
-- It's one and only argument that's passed is the player that joined.
game.Players.PlayerAdded:Connect(function(plr)
    -- Now we can do whatever we want to load the Player's data.
    local userId = "save-" .. tostring(plr.UserId) -- The Player's id.
end)

You might be wondering, what does the .. do? It joins strings together. In this example, when I joined, the userId variable would be equal to save-161615648, even if I changed my name.

Now we need to get the player’s datastore. We can do that by using the GetDataStore function that is located in DataStoreService.

-- This loads up the DataStoreService so we can use it:
local dataStoreService = game:GetService("DataStoreService")

-- The provided function is called when a player joins.
-- It's one and only argument that's passed is the player that joined.
game.Players.PlayerAdded:Connect(function(plr)
    -- Now we can do whatever we want to load the Player's data.
    local userId = "save-" .. tostring(plr.UserId) -- The Player's id.
    local datastore = dataStoreService:GetDataStore(userId) -- Yay!  We got the datastore!
end)

Let’s create a leaderstat called Gold.

-- This loads up the DataStoreService so we can use it:
local dataStoreService = game:GetService("DataStoreService")

-- The provided function is called when a player joins.
-- It's one and only argument that's passed is the player that joined.
game.Players.PlayerAdded:Connect(function(plr)
    -- Now we can do whatever we want to load the Player's data.
    local userId = "save-" .. tostring(plr.UserId) -- The Player's id.
    local datastore = dataStoreService:GetDataStore(userId) -- Yay!  We got the datastore!

    local leaderstatsFolder = Instance.new("Folder") -- Create a new folder.
    leaderstatsFolder.Name = "leaderstats" -- Do not change this, if you do, the Gold value won't show up on the leaderboards.
    leaderstatsFolder.Parent = plr -- Change the parent to the player that just joined.
    
    -- Now let's create a NumberValue called "Gold".
    local gold = Instance.new("NumberValue")  -- Create a NumberValue that will store the gold amount.
    gold.Name = "Gold" -- Change the name to Gold
    gold.Value = 0 -- The default value.
end)

Now we just need to load up the player’s save!

-- This loads up the DataStoreService so we can use it:
local dataStoreService = game:GetService("DataStoreService")

-- The provided function is called when a player joins.
-- It's one and only argument that's passed is the player that joined.
game.Players.PlayerAdded:Connect(function(plr)
    -- Now we can do whatever we want to load the Player's data.
    local userId = "save-" .. tostring(plr.UserId) -- The Player's id.
    local datastore = dataStoreService:GetDataStore(userId) -- Yay!  We got the datastore!

    local leaderstatsFolder = Instance.new("Folder") -- Create a new folder.
    leaderstatsFolder.Name = "leaderstats" -- Do not change this, if you do, the Gold value won't show up on the leaderboards.
    leaderstatsFolder.Parent = plr -- Change the parent to the player that just joined.
    
    -- Now let's create a NumberValue called "Gold".
    local gold = Instance.new("NumberValue")  -- Create a NumberValue that will store the gold amount.
    gold.Name = "Gold" -- Change the name to Gold
    gold.Value = 0 -- The default value.

    -- Get the saved gold value.
    local goldValue = datastore:GetAsync("gold")
    -- Check if the player has a save.
    if(goldValue ~= nil) then
        -- Set the value of gold to goldValue instead of 0.
        gold.Value = goldValue
    else
        -- Give the player a starting allowance?
        gold.Value = 10
    end
end)

Now it gets the save! But we need to save this data, don’t we? Let’s get when a player leaves.

-- This loads up the DataStoreService so we can use it:
local dataStoreService = game:GetService("DataStoreService")

-- The provided function is called when a player joins.
-- It's one and only argument that's passed is the player that joined.
game.Players.PlayerAdded:Connect(function(plr)
    -- Now we can do whatever we want to load the Player's data.
    local userId = "save-" .. tostring(plr.UserId) -- The Player's id.
    local datastore = dataStoreService:GetDataStore(userId) -- Yay!  We got the datastore!

    local leaderstatsFolder = Instance.new("Folder") -- Create a new folder.
    leaderstatsFolder.Name = "leaderstats" -- Do not change this, if you do, the Gold value won't show up on the leaderboards.
    leaderstatsFolder.Parent = plr -- Change the parent to the player that just joined.
    
    -- Now let's create a NumberValue called "Gold".
    local gold = Instance.new("NumberValue")  -- Create a NumberValue that will store the gold amount.
    gold.Name = "Gold" -- Change the name to Gold
    gold.Value = 0 -- The default value.

    -- Get the saved gold value.
    local goldValue = datastore:GetAsync("gold")
    -- Check if the player has a save.
    if(goldValue ~= nil) then
        -- Set the value of gold to goldValue instead of 0.
        gold.Value = goldValue
    else
        -- Give the player a starting allowance?
        gold.Value = 10
    end
end)

-- This is the same as PlayerAdded, but it's fired right
-- before a player leaves.
game.Players.PlayerRemoving:Connect(function(plr)
    local userId = "save-" .. tostring(plr.UserId) -- The Player's id.
    local datastore = dataStoreService:GetDataStore(userId)
    
    -- Get the Gold value.
    local gold = plr.leaderstats:WaitForChild("Gold")
    
    -- Save it to the datastore!
    datastore:SetAsync("gold", gold.Value)
end)

Badaboom, it saves the player’s stats when they leave, and loads them when the player joins.

DataStoreCache Module (For Intermediate Programmers)

Make a Script, not a LocalScript or ModuleScript in the ServerScriptService.
download%20(1)
Call it “SaveScript” and then we can start editing it.

Remove the first line (print("Hello, world!")) and then continue on to the next step!

First, we need to load in the module. You can do this by using the require function. Here’s some documentation: https://developer.roblox.com/en-us/api-reference/class/ModuleScript

-- Load in the module.  Make sure it's in ServerScriptService!
local dataStoreCache = require(script.Parent:WaitForChild("DataStoreCache"))

We need to get when a player joins, you can do this with the PlayerAdded event.

-- Load in the module.  Make sure it's in ServerScriptService!
local dataStoreCache = require(script.Parent:WaitForChild("DataStoreCache"))

-- This is called when a player joins.
game.Players.PlayerAdded:Connect(function(plr)
    -- `plr` is the player that joined.
end)

So, we get when a player joins, so let’s get the player’s save.

-- Load in the module.  Make sure it's in ServerScriptService!
local dataStoreCache = require(script.Parent:WaitForChild("DataStoreCache"))

-- This is called when a player joins.
game.Players.PlayerAdded:Connect(function(plr)
    -- `plr` is the player that joined.
    local datastore = dataStoreCache.new("save" .. tostring(plr.UserId))
end)

If you don’t understand what’s going on, I suggest reading some of the Vanilla Datastores section and coming back. What next? We’re going to create a leaderstat called “Gold”.

-- Load in the module.  Make sure it's in ServerScriptService!
local dataStoreCache = require(script.Parent:WaitForChild("DataStoreCache"))

-- This is called when a player joins.
game.Players.PlayerAdded:Connect(function(plr)
    -- `plr` is the player that joined.
    local datastore = dataStoreCache.new("save" .. tostring(plr.UserId))

    -- Create the leaderstats folder.
    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "leaderstats"
    leaderstats.Parent = plr
    
    -- Create a gold NumberValue for the leaderboards.
    local gold = Instance.new("NumberValue")
    gold.Name = "Gold"
    gold.Parent = leaderstats
end)

Okay, ready to load the save? Hopefully you are because it’s what we’re going to do!

-- Load in the module.  Make sure it's in ServerScriptService!
local dataStoreCache = require(script.Parent:WaitForChild("DataStoreCache"))

-- This is called when a player joins.
game.Players.PlayerAdded:Connect(function(plr)
    -- `plr` is the player that joined.
    local datastore = dataStoreCache.new("save" .. tostring(plr.UserId))

    -- Create the leaderstats folder.
    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "leaderstats"
    leaderstats.Parent = plr
    
    -- Create a gold NumberValue for the leaderboards.
    local gold = Instance.new("NumberValue")
    gold.Name = "Gold"
    gold.Parent = leaderstats

    -- Get the save
    local save = datastore:get("gold")
    
    -- Check if the player has a save or not.
    if(save ~= nil) then  -- If it's nil, then the player doesn't have a save.
        gold.Value = save -- Set the value of gold to the save's gold amount.
    else
        -- Give the player a first join allowance?
        gold.Value = 10
    end
end)

We just need to save the player’s stats when they leave.

-- Load in the module.  Make sure it's in ServerScriptService!
local dataStoreCache = require(script.Parent:WaitForChild("DataStoreCache"))

local dses = {}

-- This is called when a player joins.
game.Players.PlayerAdded:Connect(function(plr)
    -- `plr` is the player that joined.
    local datastore = dataStoreCache.new("save" .. tostring(plr.UserId))

    -- Create the leaderstats folder.
    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "leaderstats"
    leaderstats.Parent = plr
    
    -- Create a gold NumberValue for the leaderboards.
    local gold = Instance.new("NumberValue")
    gold.Name = "Gold"
    gold.Parent = leaderstats

    -- Get the save
    local save = datastore:get("gold")
    
    -- Check if the player has a save or not.
    if(save ~= nil) then  -- If it's nil, then the player doesn't have a save.
        gold.Value = save -- Set the value of gold to the save's gold amount.
    else
        -- Give the player a first join allowance?
        gold.Value = 10
    end

    -- Add the cache to a list so the leave event can use it.
    dses[plr.Name] = datastore
end)

-- Check when a player leaves.
game.Players.PlayerRemoving:Connect(function(plr)
    -- Get the datastore.
    local datastore = dses[plr.Name]
    datastore:set("gold", plr.leaderstats.Gold.Value)
    
    -- Save the data to the datastore.
    datastore:flushAll()
end)

Finished Scripts:

Vanilla Datastores
-- This loads up the DataStoreService so we can use it:
local dataStoreService = game:GetService("DataStoreService")

-- The provided function is called when a player joins.
-- It's one and only argument that's passed is the player that joined.
game.Players.PlayerAdded:Connect(function(plr)
    -- Now we can do whatever we want to load the Player's data.
    local userId = "save-" .. tostring(plr.UserId) -- The Player's id.
    local datastore = dataStoreService:GetDataStore(userId) -- Yay!  We got the datastore!

    local leaderstatsFolder = Instance.new("Folder") -- Create a new folder.
    leaderstatsFolder.Name = "leaderstats" -- Do not change this, if you do, the Gold value won't show up on the leaderboards.
    leaderstatsFolder.Parent = plr -- Change the parent to the player that just joined.
    
    -- Now let's create a NumberValue called "Gold".
    local gold = Instance.new("NumberValue")  -- Create a NumberValue that will store the gold amount.
    gold.Name = "Gold" -- Change the name to Gold
    gold.Value = 0 -- The default value.

    -- Get the saved gold value.
    local goldValue = datastore:GetAsync("gold")
    -- Check if the player has a save.
    if(goldValue ~= nil) then
        -- Set the value of gold to goldValue instead of 0.
        gold.Value = goldValue
    else
        -- Give the player a starting allowance?
        gold.Value = 10
    end
end)

-- This is the same as PlayerAdded, but it's fired right
-- before a player leaves.
game.Players.PlayerRemoving:Connect(function(plr)
    local userId = "save-" .. tostring(plr.UserId) -- The Player's id.
    local datastore = dataStoreService:GetDataStore(userId)
    
    -- Get the Gold value.
    local gold = plr.leaderstats:WaitForChild("Gold")
    
    -- Save it to the datastore!
    datastore:SetAsync("gold", gold.Value)
end)
DataStoreCache Module
-- This loads up the DataStoreService so we can use it:
local dataStoreService = game:GetService("DataStoreService")

-- The provided function is called when a player joins.
-- It's one and only argument that's passed is the player that joined.
game.Players.PlayerAdded:Connect(function(plr)
    -- Now we can do whatever we want to load the Player's data.
    local userId = "save-" .. tostring(plr.UserId) -- The Player's id.
    local datastore = dataStoreService:GetDataStore(userId) -- Yay!  We got the datastore!

    local leaderstatsFolder = Instance.new("Folder") -- Create a new folder.
    leaderstatsFolder.Name = "leaderstats" -- Do not change this, if you do, the Gold value won't show up on the leaderboards.
    leaderstatsFolder.Parent = plr -- Change the parent to the player that just joined.
    
    -- Now let's create a NumberValue called "Gold".
    local gold = Instance.new("NumberValue")  -- Create a NumberValue that will store the gold amount.
    gold.Name = "Gold" -- Change the name to Gold
    gold.Value = 0 -- The default value.

    -- Get the saved gold value.
    local goldValue = datastore:GetAsync("gold")
    -- Check if the player has a save.
    if(goldValue ~= nil) then
        -- Set the value of gold to goldValue instead of 0.
        gold.Value = goldValue
    else
        -- Give the player a starting allowance?
        gold.Value = 10
    end
end)

-- This is the same as PlayerAdded, but it's fired right
-- before a player leaves.
game.Players.PlayerRemoving:Connect(function(plr)
    local userId = "save-" .. tostring(plr.UserId) -- The Player's id.
    local datastore = dataStoreService:GetDataStore(userId)
    
    -- Get the Gold value.
    local gold = plr.leaderstats:WaitForChild("Gold")
    
    -- Save it to the datastore!
    datastore:SetAsync("gold", gold.Value)
end)

There you go, thanks for reading and I hope this helped you! :heart:
Happy coding!

- Zack

2 Likes

This topic was automatically closed after 1 minute. New replies are no longer allowed.