Problem with Leaderboard code

HEY Devs hope you are having a good day so far…Im here cause im having a tiny bug with my leaderboard code…So the leaderboard contains two values under the player EBITS(Cash) and the Level of the player and so every 10 seconds it updates the leaderboard incase theres a change in the values but the bug is ofc it doesnt update it only shows 1 Under Levels and 1 Under EBits here’s a image…I hope someone can help me and guide me on what I did wrong Thank you very much here’s the leaderboard code.

local DataStoreService = game:GetService('DataStoreService')

     local LevelsLeaderboard = DataStoreService:GetOrderedDataStore("LevelsLeaderboard");
	 local CashLeaderboard = DataStoreService:GetOrderedDataStore("CashLeaderboard")


for _,player in pairs(game.Players:GetPlayers()) do
    LevelsLeaderboard:SetAsync(player.UserId, player.leaderstats.Level.Value)
  	CashLeaderboard:SetAsync(player.UserId, player.leaderstats.EBits.Value)
end

local function updateLeaderboard()
	local succes, errormessage = pcall(function()
		local LevelData = LevelsLeaderboard:GetSortedAsync(false, 5)
		local CashData = CashLeaderboard:GetSortedAsync(false, 5)
		local LevelsPage = LevelData:GetCurrentPage()
		local CashPage = CashData:GetCurrentPage()
	
	
		
		for index, data in ipairs(LevelsPage, CashPage) do
			local Username = game.Players:GetNameFromUserIdAsync(tonumber(data.key))
			local Name = Username
			local Level = data.value
			local Cash = data.value
			local isOnLeaderboard = false
			for i,v in pairs(game.Workspace.GlobalLeaderboard.SurfaceGui.Holder:GetChildren()) do
				if v.Player.Text == Name then
					isOnLeaderboard = true
					break
				end				
			end
			if Level and Cash and isOnLeaderboard == false then
				local newLeaderboardFrame = game.ReplicatedStorage:WaitForChild("LeaderboardFrame"):Clone()
				newLeaderboardFrame.Player.Text = Name
				newLeaderboardFrame.Rank.Text = Level
				newLeaderboardFrame.EBITS.Text = Cash
				newLeaderboardFrame.Position = UDim2.new(0,0, newLeaderboardFrame.Position.Y.Scale + (.08*#game.Workspace.GlobalLeaderboard.SurfaceGui.Holder:GetChildren()),0)
				newLeaderboardFrame.Parent = game.Workspace.GlobalLeaderboard.SurfaceGui.Holder
			end
		end
	end)
	
	if succes then
	else
	end
	
	
end --End of updateLeaderboard function



while true do --Loop which updates the leaderboard every 10 seconds 
	for _, frame  in pairs(game.Workspace.GlobalLeaderboard.SurfaceGui.Holder:GetChildren()) do
		frame:Destroy()
	end
	updateLeaderboard()	
	wait(10)	 
end


4 Likes

Try changing it to update every ~45 seconds as updating it every 10 seconds can put stress on data stores, and can cause data store services to fill up which can prevent the leaderboard from updating more.

4 Likes

Also use pcall() when using :SetAsync()

1 Like

Ok I did it but nothing changed values are still one

1 Like

Ok I wrap the for loop function of the SetAsync under a pcall but it prints “SUCCESS”

1 Like

A good method that you can use instead of using your current system for ranking the player is to do this:

		for rank, data in ipairs(LevelsPage, CashPage) do
			local Username = game.Players:GetNameFromUserIdAsync(tonumber(data.key))
			local Name = Username
			local Level = data.value
			local Cash = data.value
			local isOnLeaderboard = false
			for i,v in pairs(game.Workspace.GlobalLeaderboard.SurfaceGui.Holder:GetChildren()) do
				if v.Player.Text == Name then
					isOnLeaderboard = true
					break
				end				
			end
			if Level and Cash and isOnLeaderboard == false then
				local newLeaderboardFrame = game.ReplicatedStorage:WaitForChild("LeaderboardFrame"):Clone()
				newLeaderboardFrame.Player.Text = Name
				newLeaderboardFrame.Rank.Text = rank
				newLeaderboardFrame.EBITS.Text = Cash
				newLeaderboardFrame.Position = UDim2.new(0,0, newLeaderboardFrame.Position.Y.Scale + (.08*#game.Workspace.GlobalLeaderboard.SurfaceGui.Holder:GetChildren()),0)
				newLeaderboardFrame.Parent = game.Workspace.GlobalLeaderboard.SurfaceGui.Holder
			end
		end
	end)

This new code sets the rank of the player using the for loops index.

This should fix the ranking issue.

3 Likes

ipairs takes only one arguement, so in this case only the LevelsPage will be updated

2 Likes

I updated that recently here’s the code now

local DataStoreService = game:GetService('DataStoreService')

     local LevelsLeaderboard = DataStoreService:GetOrderedDataStore("LevelsLeaderboard");
	 local CashLeaderboard = DataStoreService:GetOrderedDataStore("CashLeaderboard")


	for _,player in pairs(game.Players:GetPlayers()) do
		LevelsLeaderboard:SetAsync(player.UserId, player.leaderstats.Level.Value)
		CashLeaderboard:SetAsync(player.UserId, player.leaderstats.EBits.Value)
	end

	
	local function updateLeaderboard()
		local succes, errormessage = pcall(function()
			local LevelData = LevelsLeaderboard:GetSortedAsync(false, 5)
			local CashData = CashLeaderboard:GetSortedAsync(false, 5)
			local LevelsPage = LevelData:GetCurrentPage()
			local CashPage = CashData:GetCurrentPage()

		for rank, data in ipairs(CashPage) do
			local Username = game.Players:GetNameFromUserIdAsync(tonumber(data.key))
			local Name = Username
			local Cash = data.value
			local isOnLeaderboard = false
			for i,v in pairs(game.Workspace.GlobalLeaderboard.SurfaceGui.Holder:GetChildren()) do
				if v.Player.Text == Name then
					isOnLeaderboard = true
					break
				end				
			end
			if Cash and isOnLeaderboard == false then
				local newLeaderboardFrame = game.ReplicatedStorage:WaitForChild("LeaderboardFrame"):Clone()
				newLeaderboardFrame.Player.Text = Name
				newLeaderboardFrame.Rank.Text = rank
				newLeaderboardFrame.EBITS.Text = Cash
				newLeaderboardFrame.Position = UDim2.new(0,0, newLeaderboardFrame.Position.Y.Scale + (.08*#game.Workspace.GlobalLeaderboard.SurfaceGui.Holder:GetChildren()),0)
				newLeaderboardFrame.Parent = game.Workspace.GlobalLeaderboard.SurfaceGui.Holder
			end
		end
	end)
		

	end --End of updateLeaderboard function
	
	while true do --Loop which updates the leaderboard every 10 seconds 
		for _, frame  in pairs(game.Workspace.GlobalLeaderboard.SurfaceGui.Holder:GetChildren()) do
			frame:Destroy()
		end
		updateLeaderboard()	
		wait(10)	 
	end
1 Like

This is unnecessary as you are already clearing the Leaderboard before updating

2 Likes

To avoid this calculation, just use a UIListLayout which dynamically arranges the elements for you

1 Like

Ok I added it to the GlobalLeaderboard part now do I set the value like EBits and Levels and the player name as it’s children?

2 Likes

I may have found the problem, as according the my understanding the players EBITS and Levels will only be updated once and will not be updated after the for loop has ran as the loop that gets the players new cash value is only running on, meaning that refreshing the leaderboard is basically doing nothing except reloading the exact same data. To fix this you must try placing the for loop that gets the players EBITS and Level value inside of the refresh function.

This is the updated code:

local DataStoreService = game:GetService('DataStoreService')

     local LevelsLeaderboard = DataStoreService:GetOrderedDataStore("LevelsLeaderboard");
	 local CashLeaderboard = DataStoreService:GetOrderedDataStore("CashLeaderboard")
	
	local function updateLeaderboard()

	for _,player in pairs(game.Players:GetPlayers()) do
		LevelsLeaderboard:SetAsync(player.UserId, player.leaderstats.Level.Value)
		CashLeaderboard:SetAsync(player.UserId, player.leaderstats.EBits.Value)
	end
		local succes, errormessage = pcall(function()
			local LevelData = LevelsLeaderboard:GetSortedAsync(false, 5)
			local CashData = CashLeaderboard:GetSortedAsync(false, 5)
			local LevelsPage = LevelData:GetCurrentPage()
			local CashPage = CashData:GetCurrentPage()

		for rank, data in ipairs(CashPage) do
			local Username = game.Players:GetNameFromUserIdAsync(tonumber(data.key))
			local Name = Username
			local Cash = data.value
			local isOnLeaderboard = false
			for i,v in pairs(game.Workspace.GlobalLeaderboard.SurfaceGui.Holder:GetChildren()) do
				if v.Player.Text == Name then
					isOnLeaderboard = true
					break
				end				
			end
			if Cash and isOnLeaderboard == false then
				local newLeaderboardFrame = game.ReplicatedStorage:WaitForChild("LeaderboardFrame"):Clone()
				newLeaderboardFrame.Player.Text = Name
				newLeaderboardFrame.Rank.Text = rank
				newLeaderboardFrame.EBITS.Text = Cash
				newLeaderboardFrame.Position = UDim2.new(0,0, newLeaderboardFrame.Position.Y.Scale + (.08*#game.Workspace.GlobalLeaderboard.SurfaceGui.Holder:GetChildren()),0)
				newLeaderboardFrame.Parent = game.Workspace.GlobalLeaderboard.SurfaceGui.Holder
			end
		end
	end)
		

	end --End of updateLeaderboard function
	
	while true do --Loop which updates the leaderboard every 10 seconds 
		for _, frame  in pairs(game.Workspace.GlobalLeaderboard.SurfaceGui.Holder:GetChildren()) do
			frame:Destroy()
		end
		updateLeaderboard()	
		wait(45)	 
	end

I wrote the code down and it doesnt work plus when it updates the leaderboard it doesnt appear again.