How I Implemented DataStore2 Into My Game (And How You Could Too)

I was browsing the forum when I found a DataStore2 Post by Kampfkarren, I read the replies and decided why not show everyone how I implemented DataStore2 into my game (I must mention, I tested and fiddled around with my code, and it does work properly).

I’m not the best scripter in the world, not even close, but I do have some knowledge, and if anything in this post is helpful to you, then please feel free to like, and if it’s not, then please share your feedback, all constructive criticism is welcome! I have not been well seasoned with DataStorage in the past, however, hopefully my skills have been refined and shine in this post.

Personally, I downloaded the ROBLOX Free Model offered here

And after downloading it, I ran this command in my Command Bar in studio: game.InsertService:LoadAsset(1936396537).MainModule.Parent = workspace and placed the MainModule in ServerScriptService.

From there I inserted an empty script in ServerScriptService and began to code. (You can adapt the code from this tutorial to match any Server-Side script you want.

For the sake of this tutorial on how I added it, I will be using Coins as the Data example.

Step 1

First you need to require() the module so you can reference it and use it’s API throughout your empty script.

local DataStore2 = require(game.ServerScriptService:WaitForChild("MainModule"))

Next, we will want to set default values, the amount of something a new player will get when joining the game.

In this case, the player will get 10 coins to start with if they are new.

local defaultCoins = 10

Step 2

From here, we want to set the unique keys to the player when they join (where the data will be written to.
The problem
In usual data storage, developers create their own unique keys, like this

local valueKey = "value-"..player.UserId

The Solution
Instead of creating your own unique key for each individual player, the module does that for you! So, you just need to use the DataStore2 API

Like this, setting the name of the value and the player it’s creating the key for:

game.Players.PlayerAdded:Connect(function(player)
    local coinsDataStore = DataStore2("coins", player)
end)

All the players in the server can all have their key being called “coins” because the module will deal with keeping them separate to prevent overwriting data to different players.

Step 3

Create the leaderstats you want to save for your player, for the sake of this tutorial I will be creating the ‘leaderstats’ in the player, but I recommend creating a folder for each player in ServerStorage to optimize safety and prevent exploiters from changing or viewing those values.

game.Players.PlayerAdded:Connect(function(player)
    local coinsDataStore = DataStore2("coins", player)
    
    local leaderstats = Instance.new("IntValue", player)
    leaderstats.Name = "leaderstats"
    
    local coins = Instance.new("IntValue", leaderstats)
    coins.Name = "Coins"
end)

When making your leaderstats, do NOT set their values, as that will overwrite the defaultValue you set at the beginning of the script and could cause data-loss as the module fails to save and update the values accordingly.

What is different about DataStore2 from normal DataStorage
In DataStore2, it’s actually the value in the DataStore changing first, and not the actual value in the player, so once the DataStore Value is changed, the script will then update your points value accordingly.

NOTE:

When actually updating a players coins using DataStore2, you can either :Set() or :Increment() the value. Setting the value means, if a player has 10 coins and you :Set() to 50, the player will then have 50 coins, but with :Increment() if the player has 10 coins and you :Increment() 50 coins, now the player will have 60 coins in total.

Whichever method you use is completely situational, on if you need the player to have a set value or if it’s a round based game and you add coins every win.

The Problem
Using DataStore2 you cannot update values using the traditional method (since the DataStore is updated first, and then the player’s value.

Bad Example:

player.leaderstats.Coins.Value = player.leaderstats.Coins.Value + 50

The Solution
Use the DataStore2 API to increment or set the player’s value.

Good Example: (Clicking a part to get 15 coins)

game.Workspace:WaitForChild("CoinPart").ClickDetector.MouseClick:Connect(function(player)
    local coinsDataStore = DataStore2("coins", player) -- getting that key to write the updated value to before making the change in the player.
    
    coinsDataStore:Increment(15, defaultCoins)
end

Make sure if the script you are adding a value changing function to is different than the data-storing / leaderstat creating script - you add the DataStore2 require variable at the beginning, as well as define the same default amount for that variable so if the player has the default amount (if not data was found in the key), it increments 15 to that, and if the player doesn’t have the default amount, it still just adds 15 to whatever they have currently (if data was found in the key).
Sorry if my explanations make no sense haha, I’m just writing it out how I understand it, and hopefully someone else out there can be helped by this.

For the sake of this tutorial I will be keeping the ClickDetector script inside of the same script we’ve been using this whole time.

Step 4

Now that we have a way to increase our coins, and all of the default values and keys are created, we need a way to update the players value (when the DataStore value is updated).

Back in the PlayerAdded function, we will add the following local function to fire everytime the DataStore value is updated.

game.Players.PlayerAdded:Connect(function(player)
    local coinsDataStore = DataStore2("coins", player)

    local leaderstats = Instance.new("IntValue", player)
    leaderstats.Name = "leaderstats"

    local coins = Instance.new("IntValue", leaderstats)
    coins.Name = "Coins"

    local function coinsUpdate(updatedCoins)
        coins.Value = coinsDataStore:Get(updatedCoins)
    end

    coinsUpdate(defaultCoins)
end)

So here, when a player joins the game, it will call the function to check if there is any playerData found, if so, it will set the player’s Data to the data found, otherwise if no data was found (because they are a new player), then it will fire the function, but pass through the defaultCoins value (which we defined earlier as 10)

As of right now we have a problem…

The problem

This code only runs once when a player joins the game, we need to add something that fires the coinsUpdate function everytime the player’s value changes.

The solution

Use DataStore2’s :OnUpdate() API

If we use this API and we pass through the coinsUpdate function, then that function will fire everytime there is an update to the DataStore value (the :Increment() method we used earlier in the ClickDetector)

game.Players.PlayerAdded:Connect(function(player)
    local coinsDataStore = DataStore2("coins", player)

    local leaderstats = Instance.new("IntValue", player)
    leaderstats.Name = "leaderstats"

    local coins = Instance.new("IntValue", leaderstats)
    coins.Name = "Coins"

    local function coinsUpdate(updatedCoins)
        coins.Value = coinsDataStore:Get(updatedCoins)
    end

    coinsUpdate(defaultCoins)

    coinsDataStore:OnUpdate(coinsUpdate)
end)

This :OnUpdate() API can be reviewed and learned form on the OP by Kampfkarren

In Conclusion

The Full Script and It’s Review (Explanation line by line)

local DataStore2 = require(game.ServerScriptService:WaitForChild("MainModule"))
-- This line requires the Module script to allow us to utilize it's API and functions (like :Increment(), :OnUpdate(), :Get(), :Backup(), etc.)

local defaultCoins = 10
-- This variable sets the default coin value a new player will get upon joining the game for the first time.

game.Players.PlayerAdded:Connect(function(player) -- Fires every time a player joins the game
    local coinsDataStore = DataStore2("coins", player)
    -- Creates the 'coin' key for each player that joins the game, which can be named the same for every player as the Module Script [DataStore2()] handles making each key separate and unique for you.

    local leaderstats = Instance.new("IntValue", player)
    leaderstats.Name = "leaderstats"

    local coins = Instance.new("IntValue", leaderstats)
    coins.Name = "Coins"
    -- Here we create the standard player values (without actually setting its value, we did that earlier with the defaultValue variable

    local function coinsUpdate(updatedCoins)
        coins.Value = coinsDataStore:Get(updatedCoins)
    end
    -- This function updates the coins value

    coinsUpdate(defaultCoins)
    -- Once a new player joins the coinsUpdate function is fired, if no data is found on the key, then the (defaultCoins) variable we defined earlier will pass through, setting the players value to 0.

    -- REMEMBER: Setting the coins value will not impact data saving, as the DataStore Value is what gets saved, the players value only reflects the value inside of the DataStore, we never fully write the players value  to the key (The DataStore2 module handles all data saving and cache writing)

    coinsDataStore:OnUpdate(coinsUpdate)
    -- Once the value is changed (using the module API like :Set() or :Increment()) then we use the :OnUpdate() method to fire the coinsUpdate function and update the players value to whatever the DataStore value has been updated to.
end)

game.Workspace:WaitForChild("CoinPart").ClickDetector.MouseClick:Connect(function(player)
-- This function runs everytime a player clicks the brick in the workspace named "CoinPart"
-- Once clicked, we increment the Value saved to the Key by (15) [add 15 to whatever the value is]
    local coinsDataStore = DataStore2("coins", player) -- getting that key to write the updated value to before making the change in the player.

    coinsDataStore:Increment(15, defaultCoins)
    -- This changes the DataStore value, which once updated uses the :OnUpdate() method above to then change the players coin value.
end

And through research of the post, and the replies, and other games and how they implemented it, this is the way I chose to implement DataStore2 into my game. I have little to no clue how effective this is (as I didn’t write the DataStore2 module), but I can verify that data does indeed save in my game and for other players (as I tested it out).

I am not the best scripter out there, and there are probably a million better ways to do this, but this is how I added it into my game, and this is the way I explained it based on my understanding of it.

Thanks for taking the time to read this and I hope it helped at least someone out there :slight_smile:

Also, the Module handles saving data on PlayerRemoving, so trying to save it yourself using that function may cause data-loss by interfering with the module script.

13 Likes

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