UpdateAsync Not Working!

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)

Maybe because you can’t update something that doesn’t exist?
Verify that when obtaining the data it is not nil, when it is, use :SetAsync()

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.

No, just checked the data is nil or not.

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.

What about the PlayerRemoving function?

It doesn’t work unless I added it to the wrong line, where do I add it?

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)

Nope, it still doesn’t work. But it does fix the problem to server close the next time I have the problem.

I still need helpppppppppppppppppppppppp, I need this right now, why ain’t people answering me.

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)
3 Likes

@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.

1 Like