Custom Leaderboard

So I’ve created a custom leaderboard that is functioning but it has a few issues that I’d like to sort out before I call it finished. This is my first time doing something like this so I’m not even sure if I’ve taken correct route.

Firstly, I have a script in “ServerScriptService” that uses PlayerAdded and PlayerRemoving to update the leaderboard guis in each current player with new players or ones that have left, this works besides the fact the first player who joins won’t receive any player rows expect themselves but players two, three, four and so on will load the leaderboard fine. Does anyone have any idea why that is?

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local StarterGui = game:GetService("StarterGui")
local screenGui = StarterGui:WaitForChild("Leaderboard")

local function addRowToPlayers(player)
	local frame = ReplicatedStorage:FindFirstChild("Storage"):FindFirstChild("Storage_Interface"):FindFirstChild("PlayerRow")
	for _, p in pairs(game.Players:GetChildren()) do
		if p.Name == player.Name then
			local pGui = p:WaitForChild("PlayerGui")
			local sGui = pGui:WaitForChild("Leaderboard")
			local cloneFrame = frame:Clone()
			cloneFrame.Name = player.Name
			cloneFrame:FindFirstChild("NameLabel").TextColor3 = Color3.new(136, 102, 63)
			cloneFrame:FindFirstChild("NameLabel").Text = player.Name
			cloneFrame.Parent = sGui:WaitForChild("Backing"):WaitForChild("LeaderFrame")
		else
			local pGui = p:WaitForChild("PlayerGui")
			local sGui = pGui:WaitForChild("Leaderboard")
			local cloneFrame = frame:Clone()
			cloneFrame.Name = player.Name
			cloneFrame:FindFirstChild("NameLabel").Text = player.Name
			cloneFrame.Parent = sGui:WaitForChild("Backing"):WaitForChild("LeaderFrame")
		end
	end
	local cloneFrame = frame:Clone()
	cloneFrame.Name = player.Name
	cloneFrame:FindFirstChild("NameLabel").Text = player.Name
	cloneFrame.Parent = screenGui:WaitForChild("Backing"):WaitForChild("LeaderFrame")
end

local function removeRowFromPlayers(player)
	local leaderFrame = screenGui:WaitForChild("Backing"):WaitForChild("LeaderFrame")
	leaderFrame:WaitForChild(player.Name):Destroy()
	for _, p in pairs(game.Players:GetChildren()) do
		if p ~= player then
			local pGui = p:WaitForChild("PlayerGui")
			local sGui = pGui:WaitForChild("Leaderboard")
			local lFrame = sGui:WaitForChild("Backing"):WaitForChild("LeaderFrame")
			local row = lFrame:WaitForChild(player.Name)
			row:remove()
		end
	end
end

game.Players.PlayerAdded:Connect(addRowToPlayers)
game.Players.PlayerRemoving:Connect(removeRowFromPlayers)

Besides that I’m a tiny bit concerned on the way I’m updating the coins on leaderboard, at the moment I’m using while true do in each player(localscript) to check the coin values of each player every 2 seconds and then update the leaderboard. This works obviously but I can’t say I’m comfortable with it. Is this the right way to do it? or have I taken a bad route?

Is this supposed to show up in the player’s gui? Because you’re apparently parenting it into the StarterGui

Also use row:Destroy() since Destroy() is more efficient than Remove()

This is the simplest way but not efficient.

Ahh that bit isn’t even suppose to be there. Oopsies.

What would be a more efficient way to do the updating on the coins on leaderboards?

Is this a local script? “.PlayerAdded” doesn’t fire in local scripts. That’s why older players aren’t seeing newer players on the leaderboard.

You could listen for “.PlayerAdded” to fire on the server and then fire all clients via a RemoteEvent to inform each client that a new player (new client) has joined.