Hiya, I’m currently making a custom leaderboard but instead of the use of text labels, i’m using text buttons instead for other purposes. Upon testing, It became clear that i cannot use the new buttons that are being added, I’m wondering if there is a fix for it.
I think an issue could be the use of an in pairs loop.
Here’s the script for reference
local PlayerTable = {}
local function AddPlayer(Player)
if Player:GetRankInGroup(Group) > MinimumStaffRank or Player:GetRankInGroup(Group) < MinimumModelRank then return end
local PlayerJoined = PlayerTemplate:Clone()
PlayerJoined.TextLabel.Text = Player.Name
PlayerJoined.Name = Player.Name
PlayerJoined.Visible = true
PlayerJoined.Parent = Playerlist
PlayerTable[Player] = PlayerJoined
local Playerlist = Playerlist
end
local function RemovePlayer(Player)
local PlayerJoined = PlayerTable[Player]
PlayerJoined:Destroy()
PlayerTable[Player] = nil
end
for _,Player in pairs(game.Players:GetPlayers()) do
AddPlayer(Player)
end
game.Players.PlayerAdded:Connect(AddPlayer)
game.Players.PlayerRemoving:Connect(RemovePlayer)
for _,v in pairs(Playerlist:GetDescendants()) do
if v:IsA("TextButton") then
function OnButtonClicked()
script stuff
end
v.MouseButton1Click:Connect(OnButtonClicked)
end
end```
Possibility: you have to remember code in a for loop only runs for however many things you loop through. Once those finish, the for loop ends.
Your (potential) error: you want to put the for loop inside of a while wait() do loop, so that it will always run the for loop over and over and will register the event handler.
Reason: when the for loop ends, it will no longer see the event handler and will not do whatever code is in the event handler.
Let me know if this works! If not, please provide the other error you are having.
local PlayerTable = {}
local function AddPlayer(Player)
if Player:GetRankInGroup(Group) > MinimumStaffRank or Player:GetRankInGroup(Group) < MinimumModelRank then return end
local PlayerJoined = PlayerTemplate:Clone()
PlayerJoined.TextLabel.Text = Player.Name
PlayerJoined.Name = Player.Name
PlayerJoined.Visible = true
PlayerJoined.Parent = Playerlist
PlayerTable[Player] = PlayerJoined
local Playerlist = Playerlist
end
local function RemovePlayer(Player)
local PlayerJoined = PlayerTable[Player]
PlayerJoined:Destroy()
PlayerTable[Player] = nil
end
for _,Player in pairs(game.Players:GetPlayers()) do
AddPlayer(Player)
end
game.Players.PlayerAdded:Connect(AddPlayer)
game.Players.PlayerRemoving:Connect(RemovePlayer)
while wait() do
for _,v in pairs(Playerlist:GetDescendants()) do
if v:IsA("TextButton") then
function OnButtonClicked()
script stuff
end
v.MouseButton1Click:Connect(OnButtonClicked)
end
end
end
I don’t recommend using @xRo_Fishy’s code, it’s highly inefficient when there is a much more efficient way. You can use the ChildAdded event which detects once a new object has been added.
Here is an example using the ChildAdded event:
local Folder = -- Path to your object.
Folder.ChildAdded:Connect(function(Child)
print(Child.Name) -- A new object has been added to the Folder
end
A while loop would run every frame and would connect to a new function which could cause performance issues. Using the ChildAdded event is a much better way as it just runs the function when a new object has been added to the other object. Let me know if you have any questions.
Once the server starts, all the objects in the frame would run in that pairs loop, but if you add a new object, it’d not run in that pairs loop as the pairs loop just ended.