This method is similar to the existing BadgeService:UserHasBadgeAsync() method, but it allows you to check ownership of up to 10 badges at once for a user. It has a separate rate limit of 10 + 5 * [number of players] per minute for each server.
The following code sample demonstrates how to use this new method to check badge ownership:
local BadgeService = game:GetService("BadgeService")
local Players = game:GetService("Players")
local badgeIds = { 0000000000, 1111111111, 2222222222 } -- Change this to a list of your badge IDs
local function onPlayerAdded(player)
-- Check if the player has any of the badges
local success, result = pcall(function()
return BadgeService:CheckUserBadgesAsync(player.UserId, badgeIds)
end)
-- If there's an error, issue a warning and exit the function
if not success then
warn("Error while checking if player", player.Name, "has badges:", result)
return
end
local ownedBadgeIds = result
if #ownedBadgeIds == 0 then
print(player.Name, "does not have any of the badges")
else
print(player.Name, "has the following badges:", table.concat(ownedBadgeIds, ", "))
end
end
Players.PlayerAdded:Connect(onPlayerAdded)
If you’re currently using multiple BadgeService:UserHasBadgeAsync() calls to check badge awards for a user, we encourage you to switch to a single BadgeService:CheckUserBadgesAsync() call; it will reduce the number of network requests your experience makes and improve its badge reading speed!
Please let us know if you have any questions or run into any issues using this new method.
This is awesome! In Virtual Valley Games, we load all the badges for a player on start to make badge queries much faster later on, which is dozens of badges in Tsunami Game. It added so much time to the start (3-5 seconds, which meant every test session had a 3-5 second delay), that we had to put all of those requests in parallel. I look forward to tearing down our multitasking workflow.
Edit: Totally missed the limit of 10, but at least we will only do a few requests in parallel instead of a few dozen.
How does the response time scale with more badges? For example, if I double the badges I am querying, does it take twice as long, or less than that?
I was literally doing a check for badges to define “genres” since I am waiting for Analytics to support the kind of users that are joining my game.
Anyways, this will be helpful since there are a lot of badges I am checking for…
But why is the Limit 10…? I would love even if it automatically waits internally to perform a a new request of 10 badges, I can do it myself I know, but just why…
You can expect very small, likely unobservable increases in request latency the more badges you add. In your example, it would take much less than twice as long.
Finally it’s been out, been waiting for this no more hacky ways!
@CoffeeBurg3r One question though, what does this return though? I store my badges as frame as a way to showcase players their badges and I also use UserHasBadgeAsync, could this new method be a better practice or what?
local function _doAchievements(Inst)
if script.Parent._achievements._list.ScrollingFrame:FindFirstChild(Inst.Name) then return end
local _badgeFrame:TextButton = Inst:Clone()
table.insert(_badgeIDs, _badgeFrame:GetAttribute("_id"))
if BadgeService:UserHasBadgeAsync(Player.UserId, _badgeFrame:GetAttribute("_id")) then
print("has")
_badgesAmount += 1
_badgeFrame.LayoutOrder = 0
_badgeFrame.ImageLabel.ImageTransparency = 0
_badgeFrame.ImageLabel.ImageLabel:Destroy()
else
_badgeFrame.LayoutOrder = 1
end
_badgeFrame.Parent = script.Parent._achievements._list.ScrollingFrame
_badgeFrame.MouseButton1Down:Connect(function()
print(_badgeFrame:GetAttribute("_description"))
ReplicatedStorage._remotes._ct._effect:Fire("_attention", _badgeFrame:GetAttribute("_description"), 5)
end)
script.Parent._achievements.Frame._howMany.Text = _badgesAmount.."/"..#ReplicatedStorage._allClientsAssets._Achievemnts:GetChildren()
end
I’d recommend checking all of the badges at once, outside of each frame instance. You can then take the list of badge IDs returned and update each corresponding frame based on each ID.
Is there any reason why this is 10 and not 100? The badge web-API allows for the checking of up to 100 badges at once and I can only assume the lua API is either using this API behind-the-scenes or some variation which would be able to handle 100 badges at once. I understand if there may be a different system architecture which makes handling such a large badge count infeasible but if not, it just doesn’t make much sense to have the lua APIs have this decreased limit.
Also, this may be a very niche use-case but is there any chance we could see awardedDate being opened up to the lua API? Currently, we can only check whether a player owns a badge, knowing awarded dates can be helpful for creating badge leaderboards, etc.
GetUserInfosByUserIdsAsync should cover this use-case (at least for the UserId->Name side of things), albeit the API is finicky to work with (the response is an unordered array which you’ll have to re-construct into a usable form + the API can’t even convert strings to numbers)
A slight bit off-topic but is AwardBadge and UserHasBadgeAsync a shared rate-limit? This has been something that I’ve been questioning for ages as both documented limits are the same in-value yet aren’t ever specified as “seperate” or “shared”.
Can we expect an increase to this limit? Either the # of requests / player / min or the badges that can be included in a single request?
My game has a Bestiary which allows you to view all of the badges for the game, including limited edition ones that are no longer available, and with the current rates it takes several minutes to load the ownership status of each badge. This wouldn’t increase the update rate so there’s less friction for my players by much, if at all.
Games with hundreds of badges (like badge hunt games) currently suffer from this using Roblox’s current studio APIs.
Would also love to see a multi-get method for listing all badges of an experience, or at least the badge information (like description). Currently I have a large table of hundreds of badges, as well as their descriptions, and it’s easy for them to be outdated with changes I make on the website. Having this reliably up-to-date would be nice.
Ten seems low for addressing the need to check badges in bulk. Many experiences on Roblox have well north of this quantity. Meaning, running checks for each user will have to be split into multiple requests anyways—largely diminishing the utility. I’m of course glad for any improvements to the speed of this kind of processing, but I would have preferred a more generous limit, or a more comprehensive solution. In most cases, I’d really only want to get badges associated with the game’s universe. It would be nice if these checks could somehow be done cheaply, or with priority.