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

Saving Data

If you are playing a game, such as Twisted Murderer or Mad Paintball, and you buy in-game currency or a character, or level up, you expect that to save. You expect that, next time you play this game, your progress, your purchases, will not be gone.

So now, you're making your own game. And you want to make sure your game saves some important data for the player, too. How do you do that?

You use the DataStoreService.

The DataStoreService is an awesome API specifically meant for saving and loading data for your game. Literally in its name - it stores data! (No it doesn't mean it is a store to buy data from.)

How do you use the DataStoreService? I'll teach you.

The first step is to get the DataStoreService into your script. You do this by loading it in, just like any other ROBLOX Service.

local DSS = game:GetService("DataStoreService")

After this, you get your specific DataStore. See, the DataStoreService is not actually where you save your data, it is simply an API to get your DataStores. The DataStore is actually where all your data is saved and loaded from. And here is how to get a DataStore:

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

The DataStoreService:GetDataStore() function has two parameters, name and scope. The name parameter is required, and it just means the actual name of your DataStore. You can name your DataStore anything, even if it is "BillyBobJoeManLikesUnicorns". However, it helps to name your DataStore according to its purpose. The reason I have mine named "GeneralSaveData" is that it is where I am saving the general data for each player, so the name makes perfect sense.

The second parameter, scope, is a bit more tricky. Thankfully, this parameter is not required, so you can just leave it empty and only provide a name argument. But, if you're feeling adventurous, you can use the scope argument to have different, sort of, groups of DataStores. Let's say you saved general data for every player, but that you also saved general data for your game itself. You could then have two DataStores named "GeneralSaveData", but each in a different scope (e.g. "Players" and "Game"). You can sort of see it as a folder structure on your computer. You can have two different folders, each with files that have the same name. But because the files are in different folders, there isn't a problem!

Two folders

So, great, now you know how to make and have a DataStore! How do you use it?

Let's start with how to save data. There are couple things you're going to need in order to save your data. The first thing is, you're going to need a key. I don't mean a key to unlock a door or even a fancy wireless key for one of those push-to-start cars. No, in this case, the key is a string, and it is sort of a name for the data itself. Since we're working with data for players, we're going to want to make this key specific to the player. The best way to do this is to create the key based off of the player's userId, because this is the only thing we can be sure won't change for each player's account. What I like to do is create a function inside of my data script that generates a key by just giving it a player as an argument. Here's what I normally do:

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

For my account, my key from this function would be "uid_3276148".

The next thing you need is the data itself. The data has to be in the form of primitives (e.g. numbers, strings, and booleans), but these primitives CAN be stored in a table. Typically, this is how I store data, because it is easy to access. So let's create a mock table, assuming the player has two leaderstats - Points and Wins.

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

The last part of saving data is to actually tell your DataStore to save it! This is done using your key and your data, in that order. And then all you have to do is call the SetAsync method on your DataStore. I like to put this in its own function that takes a player as an argument, and then it calls the generateDataKey and generateDataTable functions right there. Here's what I normally do:

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

What this function does, is it saves whatever data you give it with the assigned key. Now it safely stored away in ROBLOX's systems, ready to be loaded back in at any time! We'll discuss loading data in my next blog post, since this one is so long already. So make sure to check back on Thursday, May 21 for my next post! For now, here is the script we've made, in total:

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
Posted in Scripting Tips

Commentary

Leave a Comment

alphawolvess says: May 7, 2015
This is a helpful post to those who wonder about DataStores. I recommend a post, at some point, about how to make an answer look nice. I mean examples of how to do certain things and explanations, such as CodeBlock. Including what some people don't know, using "-" to create a bullet. I'm sure there is more I don't know as well.
buoyantair says: May 19, 2015
Yes :D
jo3thebomb says: July 20, 2015
I thought this was very helpful! Thank you so much! I would recommend this to any player trying to learn DATASTORE, I was new and learned a lot about it. =)