How to make DataStores?

For this:

One thing I noticed in the thread that hasn’t been taken into account is initialized data. If a player has never saved before, their data is nil . You have to check for that, and if you find a nil value, set it equal to the default value. Otherwise you are resetting the default value to nil which I would think has undefined behaviour but apparently it is setting everything to 0 by default for you.

I’ve tried doing this:

	local playerUserId = "Player_"..player.UserId
	local data
	local data2
	local data3 
	local data4 
	local data5 -- etc.
	local success, errormessage = pcall(function()
		data = moneyDataStore:GetAsync(playerUserId)
		data2 = maxAmountDataStore:GetAsync(playerUserId)
		data3 = multiplierDataStore:GetAsync(playerUserId)
		data4 = rebirthDataStore:GetAsync(playerUserId)
		data5 = minAmountDataStore:GetAsync(playerUserId)
		-- Basically just repeat this for each datastore (data3 = (datastore):GetAsync(playerUserId), data4, data5...)
	end)
	if success then
		player.leaderstats.Money.Value = data
		player.statistics.RandomAmountMax.Value = data2
		player.leaderstats.Multiplier.Value = data3
		player.leaderstats.Rebirths.Value = data4
		player.statistics.RandomAmountMin.Value = data5
		-- You can also just repeat it for each value 
		print("Successfully loaded player data!")
	else
		player.leaderstats.Money.Value = 0
		player.statistics.RandomAmountMax.Value = 5
		player.statistics.RandomAmountMin.Value = 1
		player.leaderstats.Rebirths.Value = 0
		player.leaderstats.Multiplier.Value = 1
		print("Error loading in a player's data")
	end
end)

But this didn’t seem to work and I’m not sure what to do.

If you saved it once then it will stay that way, any changes won’t be registered because the data is already stored with all the values being set to 0. So what I suggest is you go in Test > Server and change the values on the server yourself and then switch on the client and leave the game, the data should then save.

1 Like

I tried that, and it still keeps getting reset to 0.

EDIT: Now my money giver doesn’t work.

First, you probably have to understand how DataStores work.

DataStores basically work like a dictionary. They need a key to access the data.
For instance, it might look like this inside of the DataStore

{1512612612 = 500}

Basically the first value is the key and the second one is the value that can be accessed with the key (just like dictionaries work)

Here is an easy example:

local DataStoreService = game:GetService("DataStoreService")
local MyFirstDataStore = DataStoreService:GetDataStore("MyFirstDataStore")

Alright, here we just make two variables. The first one defines the DataStoreService which is a service, just like ReplicatedStorage, Workspace, ServerStorage, … .

Then, we call a method on our DataStoreService variable which is called GetDataStore.
GetDataStore basically creates gets the DataStore with the name in the quotation marks, if there is no DataStore with that name yet, it creates one.

Alright, so we assigned our new DataStore with the name MyFirstDataStore to our MyFirstDataStore variable.

Now we actually want to save Data.
I will try to make this as easy as possible for you.

Alright, so for now we are going to give your friend who is called Ben 500 cash when he joins the game.

In our case, Ben is our key (don’t do that please, use the UserId instead as it’s more unique, Ben could change his name for example and his data would be lost).

We want the dictionary to look like this

{["Ben"] = 500}

So we do

local DataStoreService = game:GetService("DataStoreService")
local MyFirstDataStore = DataStoreService:GetDataStore("MyFirstDataStore")

MyFirstDataStore:SetAsync("Ben", 500)

Alright. Now we call a method on our MyFirstDataStore variable which is SetAsync.

SetAsync basically creates a new entry into our DataStore dictionary. The first parameter is the key and the second parameter is the actual value.

Our key is “Ben” and our value is 500.

Alright. Now we set our DataStore entry but we have to check everytimes a player joins if his name is Ben and if so, give him 500 coins.

Let’s do that!

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local MyFirstDataStore = DataStoreService:GetDataStore("MyFirstDataStore")

MyFirstDataStore:SetAsync("Ben", 500)

Players.PlayerAdded:Connect(function(playerThatJoined)
    --create leaderstats
    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "leaderstats"
    leaderstats.Parent = playerThatJoined

    local cash = Instance.new("IntValue")
    cash.Name = "Cash"
    cash.Parent = leaderstats

    --now check if the player that joined is your friend, Ben
    local async = MyFirstDataStore:GetAsync(playerThatJoined.Name) --This will become 500 (our value for Ben) if it's actually Ben. If not, it will be nil
    if async ~= nil then --Check if it's not nil
        --it's not nil. It's Ben!
        cash.Value = async --async is 500 (our value for Ben) 
    end
end) 

Alright. Now you know the basics of getting data and setting data.
Remember that DataStores are like dictionaries, they have a key and a value that is assigned to that key.

When doing DataStore:GetAsync(playerName), then it will either become the value of the key that you entered as parameter or nil.

You can store strings, numbers, tables, … inside of DataStores! They are very useful.
If you still don’t understand something, I would recommend you Youtube. Also you might want to try the DevHub, even though I found it a little worse than Youtube.

Here a script that saves when someone leaves and gets their value when someone joins:

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local MyFirstDataStore = DataStoreService:GetDataStore("MyFirstDataStore")

Players.PlayerAdded:Connect(function(playerThatJoined)
	--create leaderstats
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = playerThatJoined

	local cash = Instance.new("IntValue")
	cash.Name = "Cash"
	cash.Parent = leaderstats

	local async = MyFirstDataStore:GetAsync(playerThatJoined.UserId) 
	if async ~= nil then --Check if it's not nil
		cash.Value = async 
	end
end) 

Players.PlayerRemoving:Connect(function(playerThatLeaves)
	MyFirstDataStore:SetAsync(playerThatLeaves.UserId, playerThatLeaves.leaderstats.Cash.Value)
end)

You would also want to pcall the SetAsyncs, but you will eventually find out yourself.

I understand, but putting it in is confusing, if that makes any sense. It breaks my game.

If you just directly jump on to a stage in programming which requires knowledge of previous elements such as Tables etc, then it is pretty hard to know how to solve these kind of problems.



That being said, a really basic example to show how saving multiple stats might be like (again, This is just an idea) :

A really simple example. I will also put comments that will help you understand, leaving no way that you won’t understand the basics of saving multiple stats in one datastore, unless you’re really beginning with programming.

local statStore = game:GetService("DataStoreService"):GetDataStore("StatStore")
local players = game:GetService("Players")

players.PlayedAdded:Connect(function(player)
    local cash = Instance.new("IntValue", player)
    cash.Name = "Cash"

    local level = Instance.new("IntValue", player)
    level.Name = "Level" --Some Basic Value Instances for our stats

    local success, response = pcall(statStore.GetAsync, statStore, player.UserId) --Getting the current data for the player, wrapped in a pcall to handle errors.

    local data = response or { --This table will be used in case the response is nil, meaning theres no data.
            Cash = 100,
            Level = 1
    }

    if success then
       cash.Value = data.Cash
       level.Value = data.Level --Setting our stat values to the loaded values from the datastore / default ones.
    else
         --However you want to handle errors
    end
end)

players.PlayerRemoving:Connect(function(player)
    local saveTable = { --Just like the data table while loading data, this is for the saving structure.
        Cash = player.Cash.Value
        Level = player.Level.Value
    }

    local success, response = pcall(statStore.SetAsync, statStore, player.UserId, saveTable)
--Just like loading data, we now use the SetAsync method to save our data.

    if success then
          print("Successfully Saved Data!")
    else
          --Handle errors here, maybe retry or something?
    end
end)

But this example breaks at around line 29.
image

I should have said I haven’t tested that example, also its just a typo, you shouldn’t just copy paste examples but also use some of your own logic. Replace the saveTable variable:

local saveTable = { --Just like the data table while loading data, this is for the saving structure.
		Cash = player.Cash.Value,
		Level = player.Level.Value
}

It still didn’t work.

You know what, I give up.