I’ve made a simple hangout game for people to find new friends (nothing new, I know.) I’ve made a global leaderboard that displayed the top 50 players who have the most amount of minutes displayed from 1st, to 50th.
My issue is that whenever I run the game, the leaderboard is displayed the Minutes value as “nil,” instead of the player’s minutes in-game.
What I’ve tried to do is make ipairs go to pairs, but it had no effect. What I also tried to do is make data.Value & data.key, to time.Value & time.key, but it casued much more errors than what the original error showed.
Is there a way to make the leaderboard state the number that the player has? Here is the code that manages the leaderboard:
-- // Script Services
local DataStoreService = game:GetService("DataStoreService")
local TimeData = DataStoreService:GetOrderedDataStore("TimeData")
-- // Script Gui
local Gui = script.Parent.Leaderboard
local Rank = Gui.PlayerRank
local List = Gui.PlayerList
-- // Script Functions
local function SavePlayerData()
for _, player in pairs(game:GetService("Players"):GetPlayers()) do
local time = player.leaderstats.Time
local playerKey = "id_"..player.UserId.."_minutes"
local success, result = pcall(function()
return TimeData:SetAsync(playerKey, time.Value)
end)
if not success then
warn("⚠ | "..result)
end
end
end
local function getTop50Players()
local isAscending = false
local pageSize = 50
local pages = TimeData:GetSortedAsync(isAscending, pageSize)
local top50 = pages:GetCurrentPage()
local top = {}
for rank, data in pairs(top50) do
local dataName = data.key
local name = game:GetService("Players"):GetNameFromUserIdAsync(dataName:split('_')[2])
local data = data.Value
local currentPlayer = { Player = name, Minutes = data, Rank = rank, }
table.insert(top, rank, currentPlayer)
end
return top
end
local function ClearLeaderboard()
task.spawn(function()
for _, plrFrame in pairs(List:GetChildren()) do
if not plrFrame:IsA("Frame") then continue end
plrFrame:Destroy()
task.wait(0.25)
end
end)
end
local function UpdateLeaderboard()
SavePlayerData()
ClearLeaderboard()
local top50 = getTop50Players()
task.spawn(function()
for _, plr in ipairs(top50) do
local frame = Rank:Clone()
frame.Parent = List
frame.Player.Text = tostring(plr.Player)
frame.Minutes.Text = tostring(plr.Minutes)
frame.Rank.Text = tostring(plr.Rank)
frame.Visible = true
task.wait(0.25)
end
end)
end
-- // Script
task.spawn(function()
while true do
UpdateLeaderboard()
for count=60,0,-1 do
script.Parent.UpdateMessage.Updater.Message.Text = "Updating in.. "..count
task.wait(1)
end
end
end)
Here is the leaderboard in question, minutes is currently displaying “nil” as stated in my message.
Try adding some logging to “Minutes = data”, avoid defining two variables with the same name (I see two “data” variables here), and remove that last comma after “Rank = rank”.
So I re-made the section you were requesting stuff. Here is the piece of code:
for rank, minutes in ipairs(top50) do
local dataName = minutes.key
local name = game:GetService("Players"):GetNameFromUserIdAsync(dataName:split('_')[2])
local data = minutes.Value
local currentPlayer = { Player = name, Minutes = data, Rank = rank }
table.insert(top, rank, currentPlayer)
print(currentPlayer.Minutes)
end
The console is also agreeing with the leaderboard is showing nil.
Looks like the way you’re retrieving the data is a bit off. Not really sure but this may help.
-- // Script Services
local DataStoreService = game:GetService("DataStoreService")
local TimeData = DataStoreService:GetOrderedDataStore("TimeData")
-- // Script Gui
local Gui = script.Parent.Leaderboard
local Rank = Gui.PlayerRank
local List = Gui.PlayerList
-- // Script Functions
local function SavePlayerData()
for _, player in pairs(game:GetService("Players"):GetPlayers()) do
local time = player.leaderstats.Time
local playerKey = "id_"..player.UserId.."_minutes"
pcall(function()
TimeData:SetAsync(playerKey, time.Value)
end)
end
end
local function getTop50Players()
local isAscending = false
local pageSize = 50
local pages = TimeData:GetSortedAsync(isAscending, pageSize)
local top50 = pages:GetCurrentPage()
local top = {}
for rank, entry in pairs(top50) do
local dataKey = entry.key
local userId = dataKey:match("id_(%d+)_minutes")
local playerName = game:GetService("Players"):GetNameFromUserIdAsync(tonumber(userId))
local minutes = entry.value
local currentPlayer = { Player = playerName, Minutes = minutes, Rank = rank }
table.insert(top, rank, currentPlayer)
end
return top
end
local function ClearLeaderboard()
for _, plrFrame in pairs(List:GetChildren()) do
if plrFrame:IsA("Frame") then
plrFrame:Destroy()
end
end
end
local function UpdateLeaderboard()
SavePlayerData()
ClearLeaderboard()
local top50 = getTop50Players()
for _, plr in ipairs(top50) do
local frame = Rank:Clone()
frame.Parent = List
frame.Player.Text = tostring(plr.Player)
frame.Minutes.Text = tostring(plr.Minutes)
frame.Rank.Text = tostring(plr.Rank)
frame.Visible = true
end
end
-- // Script
task.spawn(function()
while true do
UpdateLeaderboard()
for count = 60, 0, -1 do
script.Parent.UpdateMessage.Updater.Message.Text = "Updating in.. "..count
task.wait(1)
end
end
end)
Tried not to change much and stick with your post. Didn’t test anything however.