Tutorial: How to Create an Autosaving Leaderboard

Introduction

Today we will create a Leaderboard that will be automatically saved every time the player disconnects.
Our script also includes a system that ensures that the player does not lose any data when DataStores are unavailable.


Make sure to...

  • Turn on Enable Studio Acces to API Services. You have to: Go in your Game Settings Screenshot 2021-03-03 101113 and go to the Security Tab and activate Enable Studio Acces to API Services.

    . This will help you to test the leaderboard inside Roblox Studio.

  • Publish the Game


The actual Tutorial

Insert a Script ExplorerImageIndex_6 in the ServerScriptService ExplorerImageIndex_71 . Open it (double-click), then follow me:

Variables

We need to create certain variables in order to access certain services/values much easier and faster.
--//Services
local DataStoreService = game:GetService("DataStoreService") --We need DataStoreService to save our data. 
local Players = game:getService("Players")

--//DataStore
local CurrencyData = DataStoreService:GetDataStore("CurrencyData") --This is the name under which the database will be saved. Here we have to give a name to our Database. The name must be unique, because if there is another Database in your game with the same name, it can lead to errors.

--//Configuration
local CurrencyName = "Money" --This is your currency name. This name will appear on the leaderboard. (Ex: Cash, Money, Coins, Clicks, etc.)
local StartingValue = 0 --We will set this number to our value when we create it. You can give some Starting Cash to your players.

Fetching the Data

Here we will use the Players.PlayerAdded event to figure out when a player joins. We will fetch their data, if any, and then create the leaderboard.

Players.PlayerAdded:Connect(function(player) --Detects when a new player joins. We also create a variable with the player.
    local UserData
    local success, errMsg = pcall(function() --We use pcall because sometimes the DataStore go down and we do not want the script to have errors.
        UserData = CurrencyData:GetAsync(player.UserId) --We try to get user Data using ":GetAsync()" 
    end)

    if success == false then --In case "success" returns false, it means that DataStores are down again. :/
        local doNotSave = Instance.new("Folder")
        doNotSave.Name = "DoNotSave"
        doNotSave.Parent = player
        --We create a folder called DoNotSave. When the player disconnects we will check if this folder exists, and if it does we will NOT save the data.
    else
        print("Data loaded!") --We let the player know that their data has been loaded successfully.
    end

    local leaderstats = Instance.new("Folder")  --We are creating the leaderstats folder. Here we will insert our Values.
    leaderstats.Name = "leaderstats" --If you want to see the currency in the default leaderboard keep the name ,,leaderstats''.
    leaderstats.Parent = player

    local Currency = Instance.new("IntValue") --Now we are creating an IntValue using Instance.new
    Currency.Name = CurrencyName --We set the name of the Value with the name we set above, in the variable "CurrencyName".
    Currency.Value = UserData or StartingValue --Now we set the value to what we received from the DataStore. If there is nothing (the player did not play) we set the value to StartingValue.
    Currency.Parent = leaderstats --Storing the IntValue inside of leaderstats.
end)

Saving the Data

Now we will use Players.PlayerRemoving which is fired when a player has disconnected, then save the player data immediately.

Players.PlayerRemoving:Connect(function(player) --When a player lefts or disconnects from the game we are saving the data
    local SavingPath = player.leaderstats:FindFirstChild(CurrencyName) --We are trying to find the IntValue

    if player:FindFirstChild("DoNotSave") then --We are trying to find the folder that is created if the data was not received successfully.
        warn("Player data was not saved to avoid data loss.")
    else
        CurrencyData:SetAsync(player.UserId, SavingPath.Value) --If the data was received successfully, then we can save the data without any problems.
    end)
end)

Pro Tip:
It is good to use player.UserId when saving stuff, because the User Id is impossible to change, unlike the Username or DisplayName.


FAQ

Q: Whats this? How this will help me?
A: This script creates a leaderboard. I’m sure you’ve seen that Cash / Money / etc. system in some games. That’s what it does, but a little more advanced: With a DataStore system that saves Player data, and another system that ensures no one loses anything when DataStores go down.

Q: What happens when DataStores go down?
A: The script will realize this without breaking. It will also make sure that it does NOT save data so no one loses it.

Q: Can I use this leaderboard from any script?
A: Yes of course, you can modify the values of this leaderboard from absolutely every server-sided script in your game.


This was my tutorial! Tell me if it was helpful and if you need help, just reply, and I will try to answer you! :smiley:

26 Likes

I wouldn’t consider this to be a tutorial. Comments in your code are very limited with information, and people that are new to coding or Lua will need more than just these comments.

Try breaking it down in parts rather than sending the whole entire code. Break down each part such as a part for variables, a part for your event handlers and a part for saving your data (just an example).

2 Likes

What about now? I improved it! Sorry but I’m still new at creating DevForum tutorials…

4 Likes

It’s better, but you have to explain each section. The comments in your code do not do justice to what you are accomplishing. Think of it as you are teaching people that don’t know what you know. How would you explain it to them?

In your explanation, it’s valuable to answer WHY this is important to have in your code. WHY does this make your code efficient? WHY does this work?

1 Like

I am glad you improved your tutorial. The comments are now detailed and I think a beginner would benefit from this.

4 Likes

Love this tutorial. Works flawlessly!

2 Likes