Using @ForeverHD’s UpdateAsync, when a player leaves the game, it doesn’t Update. I already turned on Studio access on APIs. I used print statements but it says nil so I really need help now.
Please reply, I need help now.
game.Players.PlayerRemoving:Connect(function(player)
if playersData then
ds:UpdateAsync(key, function(oldValue)
local previousData = oldValue or {DataId = 0}
if playersData.DataId == previousData.DataId then
playersData.DataId = playersData.DataId + 1
print(playersData)
return playersData
else
print("nil")
return nil
end
end)
end
end)
Full script:
local ds = game:GetService("DataStoreService"):GetDataStore("Wins")
local key = nil
local wins = nil
local playersData = nil
game.Players.PlayerAdded:connect(function(player)
local ls = Instance.new('Folder')
ls.Name = 'leaderstats'
ls.Parent = player
wins = Instance.new('IntValue')
wins.Name = 'Wins'
wins.Parent = ls
playersData = {DataId = wins.Value}
key = "user_" .. player.userId
local bef = ds:GetAsync(key)
if bef then
wins.Value = bef
else
if playersData then
ds:UpdateAsync(key, function(oldValue)
local previousData = oldValue or {DataId = 0}
if playersData.DataId == previousData.DataId then
playersData.DataId = playersData.DataId + 1
return playersData
else
return nil
end
end)
end
end
end)
game.Players.PlayerRemoving:Connect(function(player)
if playersData then
ds:UpdateAsync(key, function(oldValue)
local previousData = oldValue or {DataId = 0}
if playersData.DataId == previousData.DataId then
playersData.DataId = playersData.DataId + 1
print(playersData)
return playersData
else
print("nil")
return nil
end
end)
end
end)
I replace SetAsync with UpdateAsync because it writes a new value and it doesn’t overwrite previous data if nil is returned. If I use SetAsync then player losses happens sometimes.
local success,bef = pcall(function()
return ds:GetAsync(key)
end)
if success and bef ~= nil then
-- UpdateAsync
elseif success and bef == nil
-- SetAsync
end
(and remember to use pcall to prevent data from being lost)
These variables should all be in the PlayerAdded function–each player is going to have a different key, number of wins, and data. The PlayerAdded function calls once for every player, but since these variables are outside of the function, they will all be looking at the same numbers when they should be unique.
I recommend checking out either this article or this article (the second one is a little more complicated). They’re very helpful on creating DataStore systems.
In my experience, DataStore doesn’t update on PlayerRemoving in Studio tests. When you stop the test, not only does your player leave the game; the game also shuts down. Since the game shuts down, there isn’t enough time for your data to actually save.
Try using game:BindToClose(), as shown below:
game:BindToClose(function() --This will call before the server shuts down, even in a Studio test
for i,plr in pairs(game.Players:GetPlayers()) do
--Save the player's data here
end
end)
I think the main issue you’re facing is with the playersData variable. playersData is supposed to be a table that represents a specific player’s data; in @ForeverHD’s post, they use this variable with the assumption that you have it already assigned to the player’s data. To be completely honest, I’m not sure what DataId is supposed to be.
Here’s a simple version of how I would write your code:
local ds = game:GetService("DataStoreService")
--Load a player's data
function loadData(player)
--Create leaderstats values
local ls = Instance.new('Folder')
ls.Name = 'leaderstats'
ls.Parent = player
local wins = Instance.new('IntValue')
wins.Name = 'Wins'
wins.Parent = ls
--Load their saved data, if they have any
local key = "user_" .. player.userId
local bef = ds:GetAsync(key)
if bef then --If they have previous data:
wins.Value = bef.Wins --Set their leaderstats Wins value to what is saved in DataStore
else --If they do not have previous data:
print(player.Name.." is new.")
end
end
--Save a player's data
function saveData(player)
local key = "user_" .. player.userId
--Create a dictionary (a type of table) with the "Wins" index set to that player's leaderstats wins
playersData = {Wins = player.leaderstats.Wins.Value}
--Save their data with UpdateAsync
if(playersData) then
ds:UpdateAsync(key, function(oldValue)
return playersData
end)
end
end
game.Players.PlayerAdded:connect(loadData)
game.Players.PlayerRemoving:Connect(saveData)
@DryChicken has all the pieces, you just have to put them together.
So in the loop in BindToClose() that was shown, you add plr:Kick()
This will get you the PlayerRemoving event that is lacking when running in Studio.