local top = dataStorePages:GetCurrentPage()
for a,b in pairs(top) do
local userid = b.key
local wins = b.value
local username = "[Failed To Load]"
local s,e = pcall(function()
username = game.Players:GetNameFromUserIdAsync(userid)
end)
if not s then
warn("Error getting name for "..userid..". Error: "..e)
end
local image = game.Players:GetUserThumbnailAsync(userid, Enum.ThumbnailType.HeadShot, Enum.TmbnailSize.Size150x150)
table.insert(data,{username,wins,image})
print('....y e s')
end
Info, elaborations, considerations.
It’s a script inside serverscriptservice
It’s makes the GUI global leaderboard function.
Trying to make a leaderboard but when I add a print, I realized it delays like every I’m assuming .5 seconds to get 1 player’s info. It never goes past those lines of code so I want to get it instantly. This is the cause because it’s in a long yield until there are 100 players and it will never load the players’ global leaderboard so I’m saying that I can’t fix it, any solutions?
for a,b in pairs(top) do
coroutine.wrap(function()
local userid = b.key
local wins = b.value
local username = "[Failed To Load]"
local s,e = pcall(function()
username = game.Players:GetNameFromUserIdAsync(userid)
end)
if not s then
warn("Error getting name for "..userid..". Error: "..e)
end
local image = game.Players:GetUserThumbnailAsync(userid, Enum.ThumbnailType.HeadShot, Enum.TmbnailSize.Size150x150)
table.insert(data,{username,wins,image})
print('....y e s')
end)()
end
I think I should be continuing this instead of making another post because this is same topic about this so there’s no point about making a new one, to what at least I think.
The problem is that in this while wait 60 do loop, when it prints only 1 player’s stat, it skips the other 99 stats that are inside the page and waits for the other prints to complete. After the loop is done, it gets 99 more stats like it just forgotten to, I’m trying to say that it doesn’t load 99 more players.
local dataStoreService = game:GetService("DataStoreService")
local dataStore = dataStoreService:GetOrderedDataStore("Datastore1")
local sample = script:WaitForChild("Sample")
spawn(function()
while true do
for i,plr in pairs(game.Players:GetPlayers()) do
if plr.UserId>0 then--Prevent errors
local w = plr.leaderstats.Wins.Value--Get value
if w then
pcall(function()
--Wrap in a pcall so if Roblox is down, it won't error and break.
dataStore:UpdateAsync(plr.UserId,function(oldVal)
--Set new value
return tonumber(w)
end)
end)
end
end
end
local smallestFirst = false
local numberToShow = 100
local minValue = 0
local maxValue = 10e30
local pages = dataStore:GetSortedAsync(smallestFirst, numberToShow, minValue, maxValue)
local top = pages:GetCurrentPage()
local data = {}
for a,b in pairs(top) do
coroutine.wrap(function()
local userid = b.key
local wins = b.value
local username = "[Failed To Load]"
local s,e = pcall(function()
username = game.Players:GetNameFromUserIdAsync(userid)
end)
if not s then
warn("Error getting name for "..userid..". Error: "..e)
end
local image = game.Players:GetUserThumbnailAsync(userid, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size150x150)
table.insert(data,{username,wins,image})
print('....y e s')
end)()
end
print("b")
for i,v in pairs(game.Players:GetDescendants()) do
if v:IsA("UIListLayout") and v.Name == "UI" then
local scriptSave = v.Parent.Parent:FindFirstChild("GUIActivate")
if scriptSave ~= nil then
v.Parent = scriptSave
print("do the parent!!!")
end
end
end
print("is the completed")
for i,v in pairs(game.Players:GetDescendants()) do
if v:IsA("ScrollingFrame") and v.Name == "GlobalFrame" then
v:ClearAllChildren()
end
end
print("it do children clear cler")
for i,v in pairs(game.Players:GetDescendants()) do
if v:IsA("UIListLayout") and v.Name == "UI" then
local frame = v.Parent.Parent:FindFirstChild("GlobalFrame")
if frame ~= nil then
v.Parent = frame
end
end
end
print("do the parent again")
for number,d in pairs(data) do
local name = d[1]
local val = d[2]
local image = d[3]
local color = Color3.new(1,1,1)--Default color
if number == 1 then
color = Color3.new(1,1,0)--1st place color
elseif number == 2 then
color = Color3.new(0.9,0.9,0.9)--2nd place color
elseif number == 3 then
color = Color3.fromRGB(166, 112, 0)--3rd place color
end
local new = sample:Clone()
new.Name = name
new.LayoutOrder = number
new.Image.Image = image
new.Image.Place.Text = number
new.Image.Place.TextColor3 = color
new.PName.Text = name
new.Value.Text = "Wins: "..val
new.Value.TextColor3 = color
new.PName.TextColor3 = color
for i,v in pairs(game.Players:GetDescendants()) do
if v:IsA("ScrollingFrame") and v.Name == "GlobalFrame" then
new.Parent = v
print("sets 1 player of plr frame")
end
end
end
print("100 PLAYERSI NSIDE THE THING")
wait(60)
end
end)
Hmm, maybe try coroutining a partial bit of the loop’s contents instead of all of it?
for a,b in pairs(top) do
local userid = b.key
local wins = b.value
local username = "[Failed To Load]"
local s,e = pcall(function()
username = game.Players:GetNameFromUserIdAsync(userid)
end)
if not s then
warn("Error getting name for "..userid..". Error: "..e)
end
coroutine.wrap(function()
local image = game.Players:GetUserThumbnailAsync(userid, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size150x150)
table.insert(data,{username,wins,image})
print('....y e s')
end)()
end
It’s probably due to the `GetNameFromUserIdAsync taking a while, you could put the related code in another coroutine and see if that does anything, but it would still probably have that same issue mentioned before. Is there no way to give it a table containing the wins and the name of the player as a table for the value instead of just the wins?
There’s no real way for it to go faster if it has to use a yielding function such as GetNameFromUserIdAsync, again, you could also coroutine it, but the issue you had before of one player’s data being done and the rest finishing 60 seconds later may still happen.
I’m not sure how much giving a table containing the wins and the name of the player as the data’s value instead of only the wins will help, it will reduce an Async call sure, but it’ll still have to get the UserThumbnail, which may still mess up the code, and storing the name and even the Image url will have issues if the Username changes their name or their avatar, so it’s not advised now that I think about it.
The only thing I could really recommend is caching results so if you already have their name and/or their image url, no need to request for it again, GetNameFromUserIdAsync explains how you could do a simple caching system, maybe try to make something similar for both the name and the Image url, so times will be much faster. Sure the first time will still be slow as the cache will be empty, but afterwards, it would be smooth sailing
What confused me the most is it was working and it gets the stats instantly before. It was inside a GUI but I’m not sure if I should be putting it on one script so I decided to just rewrite the code because it sends warnings of sending key request and it happens because it doubles whenever there are 2 players which would cause because of using updateasync to update the player’s stat so It will be saved and be on the leaderboard, which means I have to do that.
I really don’t know why because I wasn’t really rewriting it, I was just copying and pasting codes that are needed like the code that has the error at the moment and still have different results.
To add on to what has already been said here, is there a reason why you cannot save the username alongside the UserID? If you saved the username you wouldn’t have to wait for GetNameFromUserIdAsync to finish.
Not anything there is saved or updated at all except the Win value (or the value that is used for the leaderboard)
I don’t think I should be saving and I would still go for GetNameFromUserIdAsync because it worked instantly before I merge my script from a GUI script into a ServerScriptService script and it’s confusing me that it is the function that delays now. (Not GetUserThumbnalAsync because it’s instant.)
You’ll probably want to create a caching system like @EmbatTheHybrid said. Just to clarify, since the leaderboard is global, you are saving the top 100 players in a DataStore, correct?
As the documentation says GetNameFromUserIdAsync queries the website and pauses the thread until it gets a response. There’s inevitably going to be some form of delay when that happens. Whether or not it’s noticeable is different, but in your case it seems like it is. As to why GetUserThumbnailAsync is instant, I can’t really tell you without knowing what is going on behind the scenes.
One solution you could try is waiting for all the data to be queried, and then update the UI.
Assuming this is a global leaderboard, you won’t be updating much more than once a minute, so you can removing the flashing / loading problem entirely by updating after you get the data. While it may be behind a few seconds, the reality is the player won’t notice the difference and you remove the loading issue with the UI.
My best bet is that is only retrieves the rbxthumb string for the source, which is just a formatted string. It’s not doing any actual image fetching until you put it in an ImageLabel or preload it.
What you could do is save the username and the image URL alongside the wins. Use that saved data to instantly update the values on the leaderboard, and in the background cross check it with GetNameFromUserIdAsync - if you want to make sure that you always have the most recent username. By doing that you would be able to load the leaderboard quickly, and then only have a delay in which usernames update if the player has changed their username recently.
You said that it originally worked before merging the script, would you mind clarifying what the original scripts looked like?
I don’t really get to what you mean by the flashing loading problem. Also to let you know, the main problem right now is to why it cause a delay every 0.5 seconds which would make the leaderboard GUI not load the player stats, not load the roblox ui though ONLY IF you’re talking about that. It just will never load the player stats so that’s what I’m saying.