Hi Jarred, I saw that you want to make a list manually and so without using UIListLayout, it’s understandable! Let me show you how you can achieving this result and how to improve your code a little to make it a little more performing.
Use a loop like you do may seem to be the solution to continually update the list. But we would agree to say that you don’t need to update your list every second. We need to update it only when necessary like when a player join or leave and when the resolution screen have changed to update the position and the canvas size!
You are probably wondering how you will know when you need to update the list? It’s simpler than you think! Every Instance on roblox have the signals ChildAdded and ChildRemoved, so you can use it to update your list! To do this, we are going to transform your code a little. We will put the content of your loop in a function, you can name this function like you want, for this example I named it “updatePlayerList”, it’s a name that aptly describes its utility!
Now that we have this function, we can remove your variables yScale
and finaludim2
; we no longer need them! Instead, we will create a variable named index above the loop which create new display and under the loop which destroys the displays which we no longer need. This variables will serve us to know the position of the display that we are creating or modifying.
Also we will assign the value of createdButtons[PlayerName]
to the cloned template. This would make it easier for us when we would like to destroy it.
We will also move the position assignment of the display out of your condition to be able to update it when a player leaves, joins, or when the screen resolution changes.
Now that we have changed the position of the display, we can add 1 to index for the next display that will be modified.
After the completion of the loop that creates and updates the displays, we can now utilize index to determine the number of displays in the list and update the CanvasSize of your ScrollingFrame. I assume that playerList is a ScrollingFrame ; if not, simply adjust the code to make it compatible with your UI.
I haven’t found an effective way to know the AbsoluteSize of the templates so I’ve use FindFirstChildWhichIsA to find an instance with the same ClassName as your template. I use a ternary operation to know if the result is an Instance and if it is I use the AbsoluteSize of this instance to multiply it with our variable index. You have now the perfect size for your CanvasSize!
You can use the signal GetPropertyChangedSignal to know when the size of your list updated to update all displays position and the CanvasSize of the ScrollingFrame.
Since the player who sees the list will not be notified by their own joining we must initialize your new function at the end of the code.
This is the final result after the modifications:
-- Services
local playerService = game:GetService("Players")
-- Variables
local playerList = script.Parent
local template = script.Parent.Parent.template
local createdButtons = {}
-- Functions
local function updatePlayerList()
-- Destroy display which we no longer need
for playerName, frame in pairs(createdButtons) do
-- Try to find the player in the service
local player = playerService:FindFirstChild(playerName)
if (not player) then
-- Destroy
frame:Destroy()
-- Remove from "register"
createdButton[playerName] = nil
end
end
-- Create new template
local index = 0
for _, player in pairs(playerService:GetPlayers()) do
-- Player Name
local playerName = player.Name
-- Player already have a display?
if (not createdButtons[playerName]) then
-- New display
local cloned = template:Clone()
cloned.Name = playerName
cloned.Text = playerName
cloned.UID.Value = player.UserId
cloned.Visible = true
cloned.Parent = playerList
-- Store into createdButtons
createdButtons[playerName] = cloned
end
-- Update existing frame
local frame = createdButtons[playerName]
frame.Position = UDim2.new(0, 0, 0, frame.AbsoluteSize.Y * index)
-- Update Index
index += 1
end
-- Update canvas size
local frame = playerList:FindFirstChildWhichIsA(template.ClassName)
local ySize = ((typeof(frame) == "Instance") and frame.AbsoluteSize.Y * index or 0)
playerList.CanvasSize = UDim2.new(0, 0, 0, ySize)
end
-- Connections
playerService.ChildAdded:Connect(updatePlayerList) -- Update list when a player enter.
playerService.ChildRemoved:Connect(updatePlayerList) -- Update list when a player leave.
playerList:GetPropertyChangedSignal("AbsoluteSize"):Connect(updatePlayerList) -- Update list when the screen resolution change.
-- Initialize
updatePlayerList()
I hope I have helped you to understand how to make it work better, if you have question, don’t hesitate to ask me!