Whats the best way to make a leaderboard with profile service?

I tried to research this question and found nothing except for you cant use profiles for a global leaderboard

Alright so I was searching this question forever yesterday, and I actually found that it was pretty simple after doing it by myself, and not so different from other datastores (well actually it was kind of different).

So yeah like I said, it’s pretty simple, and so let me show you the method.

So first, for every stat that you want to include for your leaderboard, you have to create an ordered datastore for it:

local WinsLeaderboard = DataStoreService:GetOrderedDataStore("Wins")
local PointsLeaderboard = DataStoreService`Preformatted text`:GetOrderedDataStore("Points")
local RebirthsLeaderboard = DataStoreService:GetOrderedDataStore("Rebirths")

Next Step:

Now the next thing you want to do is create your helper function. I’m not sure if all the pcalls are necessary, but the reason why I included separate ones was so that one error didn’t have to restart the whole setasync process. Anyways, what this function will do is for every player in the server, it will add their data to the ordered datastore. You setasync for each stat that you want to include:

local function SetPlayerLeaderboardData(player)
	local PlayerData = ProfileManager.Profiles[player].Data
	local success1, err1, success2, err2, success3, err3
	repeat
		success1, err1 = pcall(function()
			WinsLeaderboard:SetAsync(tostring(player.UserId), PlayerData.Wins)
		end)
	until success1
	repeat
		success2, err2 = pcall(function()
			PointsLeaderboard:SetAsync(tostring(player.UserId), PlayerData.Points)
		end)
	until success2
	repeat
		success3, err3 = pcall(function()
			RebirthsLeaderboard:SetAsync(tostring(player.UserId), PlayerData.Rebirths)
		end)
	until success3
end
-- Basically just doing repeats until all the data is added successfully

When you do that, in our main function, we will call it:

local function updateLeaderboard()
	for i, plr in ipairs(Players:GetChildren()) do
		SetPlayerLeaderboardData(plr) -- Doing it for every player
	end

Next Step:

Now the next thing you do is you create a page for each ordered datastore that you have.

-- This is just settings
	local ascending = false
	local pageMax = 100
	local minValue = 1
	local maxValue = 10e30
	-----------------------
	
	-- Initializations
	local success1, err1, success2, err2, success3, err3
	local WinsPages, PointsPages, RebirthsPages
	-------------------------
	
	-- This is the main stuff
	repeat
		success1, err1 = pcall(function()
			WinsPages = WinsLeaderboard:GetSortedAsync(ascending, pageMax, minValue, maxValue)
		end)
	until success1
	
	repeat
		success2, err2 = pcall(function()
			PointsPages = PointsLeaderboard:GetSortedAsync(ascending, pageMax, minValue, maxValue)
		end)
	until success2
	
	repeat
		success3, err3 = pcall(function()
			RebirthsPages = RebirthsLeaderboard:GetSortedAsync(ascending, pageMax, minValue, maxValue)
		end)
	until success3
	
	local WinsPages = WinsLeaderboard:GetSortedAsync(ascending, pageMax, minValue, maxValue)
	local PointsPages = PointsLeaderboard:GetSortedAsync(ascending, pageMax, minValue, maxValue)
	local RebirthsPages = RebirthsLeaderboard:GetSortedAsync(ascending, pageMax, minValue, maxValue)

	local WinData = WinsPages:GetCurrentPage()
	local PointData = PointsPages:GetCurrentPage()
	local RebirthData = RebirthsPages:GetCurrentPage()

– We’re just getting our pages sorted here.

I mean if all you wanted is to get your leaderboards into a datastore then I guess that’s the end, but I wanted to get mine into a surface GUI leaderboard.

for i, entry in WinData do
		local userId = entry.key
		local Wins = entry.value
------------------------ SETTINGS VARS
		local username = "[Failed To Load]"
		local success, err = pcall(function()
			username = game.Players:GetNameFromUserIdAsync(userId)
		end)
        local profileImage = Players:GetUserThumbnailAsync(userId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size150x150)
------------------------------------------------

So first as you can see here, I’m sorting through the win ordered data store.
If you are wondering what entry.key and what entry.value is then just look back up here:

WinsLeaderboard:SetAsync(tostring(player.UserId), PlayerData.Wins) -- UserId is key, Wins is the value

Now about the settings that I put, this is so that when I made my leaderboard, I could show their name and also their profile image.

Now you just rinse and repeat for every other stat that you put.

And that’s basically it, I have more code, on the actual leaderboard, but I would assume you already know how to create one already.

all of these end up being nil why is that?

i think its something with the profile variable

local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")

local CoinsLeaderboard = DataStoreService:GetOrderedDataStore("Coins")
local Manager = require(script.Parent.Parent.Parent.Data.Manager)

local function SetPlayerLeaderboardData(player)
	local profile = Manager.Profiles[player]

	local success1, err1
	
	repeat
		success1, err1 = pcall(function()
			CoinsLeaderboard:SetAsync(tostring(player.UserId), profile.Data.CurrencyData.Coins)
		end)
	until success1
end

local function updateLeaderboard()
	for i, plr in ipairs(Players:GetPlayers()) do
		SetPlayerLeaderboardData(plr)
	end
	
	local ascending = false
	local pageMax = 100
	local minValue = 1
	local maxValue = 10e30
	
	local success1, err1
	local CoinsPages

	repeat
		success1, err1 = pcall(function()
			CoinsPages = CoinsLeaderboard:GetSortedAsync(ascending, pageMax, minValue, maxValue)
		end)
	until success1
	
	local CoinsPages = CoinsLeaderboard:GetSortedAsync(ascending, pageMax, minValue, maxValue)
	local CoinsData = CoinsPages:GetCurrentPage()
	
	local Coins
	local Username
	local ProfileImage
	
	for i, entry in CoinsData do
		local userId = entry.key
		Coins = entry.value
		
		local username = "[Failed To Load]"
		
		local success, err = pcall(function()
			Username = Players:GetNameFromUserIdAsync(userId)
		end)
		ProfileImage = Players:GetUserThumbnailAsync(userId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420)		
	end
	
	print(Coins, Username, ProfileImage)
	
end

updateLeaderboard()
1 Like

Oh yeah, I forgot to show one last step, I think you are getting nil because you are setting the data before the data actually exists. This was my personal function for calling the updateLeaderboard() function:

local UpdateCycle = coroutine.wrap(function() -- I put this in a coroutine just in case I planned on adding anything else to the script
	task.delay(5, function() -- the first function starts 5 seconds after the server begins so that the data is ready by then
		while true do
			updateLeaderboard()
			task.wait(300) -- updates every 5 minutes
		end
	end)
end)

UpdateCycle() -- Call this instead of updateLeaderboard() directly to start the cycle

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.