Help with datastore 2

Can someone plz tell me whats wrong with my datastore2script im trying to make a game with my friend and we just need to save the players data.

(Im Trying To Make It So When The Player Touches The Part It Loads The Stats But It Keeps Saying UserStats Is A Nil Value.)
Heres the script:

local DataStore2 = require(game.ServerScriptService:WaitForChild("MainModule"))
local userKey = "Player_".. math.random(1,11111111)
DataStore2(userKey, "Stats")

local function setDataTable()
	local UserData = {
		Stats = {
			["XP"] = 0,
		},
	};
end

game.Players.PlayerAdded:Connect(function(plr)
	local UserStats = DataStore2(userKey,plr):Get(setDataTable())
	
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	
	local Experience = Instance.new("IntValue")
	Experience.Name = "XP"
	
	local statsData = DataStore2("Stats", plr)
	
	local function UpdateStats(UpdatedValue)
		Experience.Value = UserStats:Get(UpdatedValue).XP
	end
	
	UpdateStats(UserStats.Stats)
	
	UserStats:OnUpdate(UpdateStats)
	
	leaderstats.Parent = plr
	Experience.Parent = leaderstats
	
	workspace.statsLoader.Touched:Connect(function()
		UserStats.Stats.XP = UserStats.Stats.XP + 1
		UserStats:Set(UserStats.Stats)
	end)
end)

Here Is The Error From The Output:

17:55:44.754 - ServerScriptService.statsLoader:28: attempt to index local ‘UserStats’ (a nil value)

1 Like
Relevant API

DataStore2 DataStore2(dataStoreName, player)

Example usage: local coinStore = DataStore2(“coins”, player)

This is what the module returns when you require it. You usually use this on PlayerAdded. Note that the data store name will not be what the name of the data store (because of how the saving method works).

Variant DataStore2:Get(defaultValue=nil, dontAttemptGet=false)

Example usage: coinStore:Get(0)

If there is no cached value, it will attempt to get the value in the data store. Otherwise, it’ll return the cached value. If whatever value it gets is nil, it will return the defaultValue passed. If dontAttemptGet is true, then it will return nil if there is no cached value.

Variant DataStore2:GetTable(defaultValue=nil)

Example usage: coinStore:GetTable({ coins = 0, gems = 0 })

Identical to :Get() only instead of only using the default value if the table is nil, GetTable will check the value from Get (which must be a table) to check if it has every key provided in the default value. If it does not, it will add the key.

So for 1 this probably shouldn’t exist

should be

local UserStats = DataStore2("UserStats", plr):GetTable(setDataTable())

setDataTable() needs to return your userData
as @Hexlinee mentioned or just not be in a function.
So something like:

local defaultStats = {}
defaultStats.XP = 0
--then ...
local UserStats = DataStore2("UserStats", plr):GetTable(defaultStats) 
2 Likes

I believe that is your problem, try removing it to see if it’ll fix it.
Changing the key will also wipe the players data, which could be the main cause to your problem.

So:

  1. Your function setDataTable, as mentioned by the above replies, does not return data, only nil, and it is probably causing the error.

  1. Your function UpdateStats, inside your PlayerAdded connection, is indexing UserStats when it should be indexing the datastore created by Datastore2(userKey, plr).
    The key should also be different, but you should also use the return from that datastore for Get and Set calls instead of UserStats itself. I have some examples down here:

Beginning of the PlayerAdded connection:

game.Players.PlayerAdded:Connect(function(plr)
    local UserStore = Datastore2("UserStats", plr)

    local UserStats = UserStore:Get(setDataTable())

Start of local function UpdateStats:

local function UpdateStats(UpdatedValue)
    Experience.Value = UpdatedValue.Stats.XP
end

UpdateStats(UserStats)

UserStore:OnUpdate(UpdateStats)

.Touched connection:
Note: This is actually incorrect, please read the next point.

workspace.statsLoader.Touched:Connect(function()
	UserStats.Stats.XP = UserStats.Stats.XP + 1
	UserStore:Set(UserStats)
end)

  1. Your .Touched function never checks who (or what) is touching statsLoader. It could be anything at all, and therefore, you should check if the player’s character touched it. This can be done by seeing if the part parameter returned by .Touched is a child of the targeted player’s character:
workspace.statsLoader.Touched:Connect(function(hit)
    -- hit represents the part that hit statsLoader
    -- if a part of a player's character hit this,
    -- it would be a child of the character model.
    if hit.Parent ~= nil and hit.Parent == plr.Character then
        UserStats.Stats.XP = UserStats.Stats.XP + 1
        UserStore:Set(UserStats)
    end
end)

You should also follow everything these above posts said, their information is pretty valuable.

2 Likes