GetAsync continues to return nil

I am attempting to build a physical leaderboard that uses Data Stores to rank players based on the number of minutes spent in the game.

I began by following along to this video tutorial: https://youtu.be/sXpuGnVzsxw . It is a physical leaderboard that displays a “wins” value stored in the player and displayed in that upper right ui. Does that thing have a name?

I managed to successfully build and code the Youtube model, but when I started to tweak the script I started running into issues. Since I do not have a leaderboard ui to pull stats from, I set the update loop to run once every minute and tried to have it add one to whatever preexisting number was there.

After some poking around the Internet, I came to the conclusion that I needed to use the GetAsync function of the Ordered Data Store in order to figure out how many minutes to add one to, as seen below:

local Players = game:GetService("Players")	
	   	for _, player in pairs(game.Players:GetPlayers()) do
			local playerKey = "Player_"..player.UserId
			print(player)
			print(playerKey)
			local success, err = pcall(function()
				oldMinutes = WinsLeaderboard:GetAsync("Player_" .. playerKey) or 0
			end)
			if success then
			minutes = oldMinutes
			print(minutes)
			end
		
			local success, err = pcall(function()
				WinsLeaderboard:SetAsync(player.UserId, minutes+1)
			end)
		
		end

(this thing being inside a while true loop with a wait(60) at the end)

When I ran the script, it correctly printed the player’s name and what I believe is the correct playerKey, but printed nil for the oldMinutes/GetAsync value. Thinking the Data Store key needed a value, I added the “or 0” and oldMinutes printed 0. So then I sat and waited for a minute while the board updated, but instead of adding 1 to the zero (and presumably ending up with 1), it just printed 0 again.

Am I doing something wrong GetAsync? Is there a problem elsewhere with the code that’s causing this issue? Or am I just going about things in the exact wrong way?

I am relatively new to both scripting and lua and this is my first attempt at using Data Stores, so apologies if it shows. Since I am so green, painfully didactic explanations are appreciated. The complete script is attached below, although only the part seen above (and the wait(60) towards the end) are my own contributions. The rest was pulled from the Youtube tutorial.

local DataStoreService = game:GetService("DataStoreService")
local WinsLeaderboard = DataStoreService:GetOrderedDataStore("WinsLeaderboard")


local function updateLeaderboard()
        local success, errorMessage = pcall (function()
                local Data = WinsLeaderboard:GetSortedAsync(false, 5)
                local WinsPage = Data:GetCurrentPage()
                for Rank, data in ipairs(WinsPage) do
                       local userName = game.Players:GetNameFromUserIdAsync(tonumber(data.key))
                       local Name = userName
                       local Wins = data.value
                       local isOnLeaderboard = false
                       for i, v in pairs(game.Workspace.GlobalLeaderboard.LeaderboardGUI.Holder:GetChildren()) do
                             if v.Player.Text == Name then
                                  isOnLeaderboard = true
                                  break
                           end
                    end

                     if Wins and isOnLeaderboard == false then
                            local newLbFrame = game.ReplicatedStorage:WaitForChild("LeaderboardFrame"):Clone()
                            newLbFrame.Player.Text = Name
                            newLbFrame.Wins.Text = Wins 
                            newLbFrame.Rank.Text = "#"..Rank
                            newLbFrame.Position = UDim2.new(0, 0, newLbFrame.Position.Y.Scale + (.11 * #game.Workspace.GlobalLeaderboard.LeaderboardGUI.Holder:GetChildren()), 0)
                            newLbFrame.Parent = game.Workspace.GlobalLeaderboard.LeaderboardGUI.Holder
                     end
              end
      end)

      if not success then
            print(errorMessage)
      end
end

while true do
local Players = game:GetService("Players")	
	   	for _, player in pairs(game.Players:GetPlayers()) do
			local playerKey = "Player_"..player.UserId
			print(player)
			print(playerKey)
			local success, err = pcall(function()
				oldMinutes = WinsLeaderboard:GetAsync("Player_" .. playerKey) or 0
			end)
			if success then
			minutes = oldMinutes
			print(minutes)
			end
		
			local success, err = pcall(function()
				WinsLeaderboard:SetAsync(player.UserId, minutes+1)
			end)
		
		end

        for _, frame in pairs(game.Workspace.GlobalLeaderboard.LeaderboardGUI.Holder:GetChildren()) do
              frame:Destroy()
        end

        updateLeaderboard()
        print("Updated!")

        wait(60)
end
1 Like

When you call GetAsync, you are using ““Player_” … playerKey”, as the key. But when you try to save to the store with SetAsync, you are using just “player.UserId”, as the key to save to.

You are saving the data to a different slot in the DataStore than you are getting from.

To fix this, just use “player.UserId” as the key for both.

For example:

--when you get
local success, err = pcall(function()

	oldMinutes = WinsLeaderboard:GetAsync(player.UserId) or 0
end)

--when you set
local success, err = pcall(function()				 
   
    WinsLeaderboard:SetAsync(player.UserId, minutes+1)
end)
1 Like

Wow, several hours staring at this and I didn’t even notice! Thanks for the advice and the quick response

1 Like