Scripting Helpers is winding down operations and is now read-only. More info→
← Blog Home

Loading Data and Implementing Saving

Welcome back! Two weeks ago, we discussed saving player data using a nifty tool called DataStores. Today, we're going to learn about loading this data. Because what good is saving data if you never load it back in and use it? Absolutely none!

First, let us get a quick refresh on what we got done last time. Here is all the code we wrote in the Saving Data article:


local DSS = game:GetService("DataStoreService")

local datastore = DSS:GetDataStore("GeneralSaveData", "Players")

function generateDataKey(player)
    local ret = "uid_" .. player.userId
    return ret
end

function generateDataTable(player)
    local dataTable = {
        Points = player.leaderstats.Points.Value,
        Wins = player.leaderstats.Wins.Value
    }
    return dataTable
end

function saveDataForPlayer(player)
    local key = generateDataKey(player)
    local data = generateDataTable(player)
    datastore:SetAsync(key, data)
end

So, from this, how can we load in our data again? Say, when the player joins the game on a new server? It's actually sort of simple. We will use our datastore variable's :GetAsync(key)' method. Keep in mind, we used ourgenerateDataKey` function to generate a key to store our entire data table with. So we will use this function again to get that data table back! Here's what I mean:

function loadDataForPlayer(player)
    local key = generateDataKey(player)
    local data = datastore:GetAsync(key)
end

So, our function now loads the data in. But how do we go about using this data and giving the player their stats back? My answer would be the same way we got the data in the first place - just setting one value to another. In our generateDataTable function, we wrote this:

Points = player.leaderstats.Points.Value

So, now, we will write something like this:

player.leaderstats.Points.Value = data.Points

Make sense? We're taking the value we saved FROM the Points leaderstat, and we're just putting it back there! So let's make our new inputDataToPlayer function.

function inputDataToPlayer(player, data)
    player.leaderstats.Points.Value = data.Points
    player.leaderstats.Wins.Value = data.Wins
end

And now, let's alter our loadDataForPlayer function to call inputDataToPlayer

function loadDataForPlayer(player)
    local key = generateDataKey(player)
    local data = datastore:GetAsync(key)
    inputDataToPlayer(player, data)
end

Voila! All of our functions are written!

But one problem.

Nothing really works...

Why?

Well, we've written a lot of functions. But we haven't actually called our save or load functions anywhere! But, when SHOULD we call these functions? Let's discuss this.

When to load data...Well, probably only need to load a player's data once - when they join the game.

What about saving? Times to save data are more complicated. At least when the player leaves the game...And probably more often than that, too. Maybe we should save every time the player's Win stat changes, since that one seems important and will only happen once every round. Yeah, let's go with that!

So here is how we implement this (if you don't know about Events, please refer to this blog post):

game.Players.PlayerAdded:connect(function(player)
    loadDataForPlayer(player) --Load first thing when they join
    player.leaderstats.Wins.Changed:connect(function()
        saveDataForPlayer(player) --Save the data when Wins changes value
    end)
end)

game.Players.PlayerRemoving:connect(saveDataForPlayer) --Save data when the player leaves the game

And that's it! Our saving and loading data idea works now that we've made all our functions and implemented them! Keep in mind, you will have to alter some of these functions to make them work for your game, but the general concept is the same.

And, to close out, here is all the code compiled into one:

local DSS = game:GetService("DataStoreService")

local datastore = DSS:GetDataStore("GeneralSaveData", "Players")

function generateDataKey(player)
    local ret = "uid_" .. player.userId
    return ret
end

function generateDataTable(player)
    local dataTable = {
        Points = player.leaderstats.Points.Value,
        Wins = player.leaderstats.Wins.Value
    }
    return dataTable
end

function saveDataForPlayer(player)
    local key = generateDataKey(player)
    local data = generateDataTable(player)
    datastore:SetAsync(key, data)
end

function inputDataToPlayer(player, data)
    player.leaderstats.Points.Value = data.Points
    player.leaderstats.Wins.Value = data.Wins
end

function loadDataForPlayer(player)
    local key = generateDataKey(player)
    local data = datastore:GetAsync(key)
    inputDataToPlayer(player, data)
end

game.Players.PlayerAdded:connect(function(player)
    loadDataForPlayer(player) --Load first thing when they join
    player.leaderstats.Wins.Changed:connect(function()
        saveDataForPlayer(player) --Save the data when Wins changes value
    end)
end)

game.Players.PlayerRemoving:connect(saveDataForPlayer) --Save data when the player leaves the game
Posted in Scripting Tips

Commentary

Leave a Comment