I want it so Pebbles and Value both save and load, but when I join the game the output says 20:40:40.729 - ServerScriptService.leaderstats:21: attempt to index local 'SavedData' (a number value)
local DataStore = game:GetService("DataStoreService"):GetDataStore('RockData12') game.Players.PlayerAdded:Connect(function(player) local key = player.UserId local leaderstats = Instance.new("Folder") leaderstats.Name = 'leaderstats' leaderstats.Parent = player local Pebbles = Instance.new("IntValue") Pebbles.Name = 'Pebbles' Pebbles.Value = 0 Pebbles.Parent = leaderstats local level = Instance.new("IntValue") level.Name = 'Level' level.Value = 0 level.Parent = leaderstats local SavedData = DataStore:GetAsync(key) if SavedData then player.leaderstats.Pebbles.Value = SavedData[1] player.leaderstats.Level.Value = SavedData[2] else local StartValues = {Pebbles.Value, level.Value} DataStore:SetAsync(key, StartValues) end end) game.Players.PlayerRemoving:Connect(function(player) local key = player.UserId local CurrentValue = {player.leaderstats.Pebbles.Value} local LevelValue = {player.leaderstats.Level.Value} DataStore:SetAsync(key, CurrentValue[1], LevelValue[2]) end) game:BindToClose(function() for i,v in pairs(game.Players:GetPlayers()) do if v then v:Kick() end end wait(3) end)
The reason for your error is because SavedData
is not a table
, rather a number
. You are attempting to index that number. Lua does not support indexing numbers. In your PlayerRemoving
event listener you attempt to save more than one value. The third argument and so on will be discarded; only the second argument is saved. You should instead save a table
. Instead of saving two individual tables, just store one table, specifically an array, like so:
DataStore:SetAsync(key, { player.leaderstats.Pebbles.Value, player.leaderstats.Level.Value })
Think of arrays as mappings from 1...#array to arbitrary values. You can get the first element of the array with array[1]
, second element with array[2]
, and so on.
Example:
local arr = {"hello", "world"} print(arr[1], arr[2]) --> hello world
Index 1 in your case will be the pebbles value and index 2 is the level.
Now, your game:BindToClose()
logic is not very great. You should read this tutorial on how to properly save your player's data.
I'm going to supplement incapaxx's answer with the following code:
local DataStore = game:GetService("DataStoreService"):GetDataStore('RockData12') game.Players.PlayerAdded:Connect(function(player) local key = player.UserId local leaderstats = Instance.new("Folder") leaderstats.Name = 'leaderstats' leaderstats.Parent = player local Pebbles = Instance.new("IntValue") Pebbles.Name = 'Pebbles' Pebbles.Value = 0 Pebbles.Parent = leaderstats local level = Instance.new("IntValue") level.Name = 'Level' level.Value = 0 level.Parent = leaderstats local SavedData = DataStore:GetAsync(key) or 0 if SavedData then player.leaderstats.Pebbles.Value = SavedData[1] player.leaderstats.Level.Value = SavedData[2] else local StartValues = {Pebbles.Value, level.Value} DataStore:SetAsync(key, StartValues) end end) game.Players.PlayerRemoving:Connect(function(player) local key = player.UserId local CurrentValue = player.leaderstats.Pebbles.Value local LevelValue = player.leaderstats.Level.Value local SaveArray = {CurrentValue, LevelValue} DataStore:SetAsync(key, SaveArray) end) -- You can edit the BindToClose Function as needed from incapaxx's link game:BindToClose(function() for i,v in pairs(game.Players:GetPlayers()) do if v then v:Kick() end end wait(3) end)
I'm also just going to point out that when you wrote:
local LevelValue = {player.leaderstats.Level.Value} DataStore:SetAsync(key, CurrentValue[1], LevelValue[2])
within the LevelValue Table, the placement of "player.leaderstats.Level.Value" is in the first position (thus it would be LevelValue[1] instead) However, since the arrays you provided are both only 1 variable long, they would cause an error when attempting to use setasync.