I am making my own game and I got issues with my datastore script. It saves and retrieves the values, but when the player leaves the game. It for some reason reads the wrong value(the value that was saved manually by me there previously) from the leaderstats. I already tried so many things it gets the right player, I use the right directory and just everything should work, but it doesn’t…
local players = game:GetService("Players")
local DataStore = game:GetService("DataStoreService")
local ds = DataStore:GetDataStore("Leaderstats")
players.PlayerAdded:Connect(function(plr)
local success, response = pcall(function()
data = ds:GetAsync(tostring(plr.UserId))
end)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = plr
local coins= Instance.new("IntValue")
coins.Name = "Coins"
coins.Parent = leaderstats
coins.Value = 100
local rank = Instance.new("StringValue")
rank.Name = "Rank"
rank.Parent = leaderstats
rank.Value = "Begginer"
if data then
rank.Value = data[2]
coins.Value = data[1]
end
end)
players.PlayerRemoving:Connect(function(plr)
local save = {plr.leaderstats.Coins.Value, plr.leaderstats.Rank.Value}
print(save) --
ds:SetAsync(tostring(plr.UserId), save)
end)
I manually setted a value to be stored in the datastore for testing purposes and when I tried printing what the script was reading the value I manually stored there before.
Here:
local save = {plr.leaderstats.Coins.Value, plr.leaderstats.Rank.Value}
print(save) --
local success, response = pcall(function()
local data = ds:GetAsync(tostring(plr.UserId))
return data
end)
Adding local in front of data to make it a local variable. return data passes the value of data to response.
Replace:
To:
if response then
rank.Value = data[2]
coins.Value = data[1]
end
data is a variable inside of another function, Lua cannot read it. However, it can read the value of response.
EDIT:
Change:
if response then
rank.Value = data[2]
coins.Value = data[1]
end
To:
if response then
if typeof(response) == "table" then
rank.Value = data[2]
coins.Value = data[1]
end
else
ds:SetAsync(tostring(plr.UserId), {coins.Value, rank.Value})
end
SetAsync should only be used when it’s the player’s first time playing. It will not update the player’s data in other servers. Instead, you have to use UpdateAsync within the PlayerRemoving event to update it for other servers.
Change:
To:
players.PlayerRemoving:Connect(function(plr)
local save = {plr.leaderstats.Coins.Value, plr.leaderstats.Rank.Value}
print(save) --
ds:UpdateAsync(tostring(plr.UserId), function(oldData)
local newData = save or oldData
return newData
end)
end)
Part 2: Efficiency
The code below does not include the edits from Part 1. Make sure you include the edits.
We know the PlayerAdded event fires when a player is added to the game. The drawback is sometimes it doesn’t fire, leaving the player with no leaderstats nor data at all.
To fix it so the player gets their initial data no matter what:
Change:
To:
local function onPlayerEntered(plr)
local success, response = pcall(function()
data = ds:GetAsync(tostring(plr.UserId))
end)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = plr
local coins= Instance.new("IntValue")
coins.Name = "Coins"
coins.Parent = leaderstats
coins.Value = 100
local rank = Instance.new("StringValue")
rank.Name = "Rank"
rank.Parent = leaderstats
rank.Value = "Begginer"
if data then
rank.Value = data[2]
coins.Value = data[1]
end
end
for _, plr in pairs(players:GetPlayers()) do
local thread = coroutine.wrap(function())
onPlayerEntered(plr)
end)
thread()
end
players.PlayerAdded:Connect(onPlayerEntered)
coroutine.wrap basically performs a function in another CPU thread, which is useful for simultaneous tasks, to give the data to the player as soon as possible.
It reads the wrong value because you are using dot notation, it shouldn’t be used for DataStores. Instead of writing leaderstats.Coins, use leaderstats:FindFirstChild("Coins").
The dot notation only works for serialized objects. If you don’t know, they are objects that were created by you in Studio, not the script.