Don’t use a wait() loop, they are inefficient and have a variety of issues associated with them. Try a heartbeat loop instead.
I assume you are destroying and recreating a frame each iteration? Try instead to just assign a frame to each player, and only add/destroy when a player joins or leaves.
I don’t know why your GUI is freezing. Is it perhaps something to do with destroying the label? If a new player joins, then DestroyLabel is fired, but his label doesn’t exist yet. So perhaps that may be the issue.
I tried doing this, but the Player Added code doesn’t seem to work. It isn’t renaming the Temp clone.
What have I done wrong?
local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local RunService = game:GetService("RunService")
RunService.Heartbeat:Connect(function()
for _, player in pairs(game.Players:GetPlayers()) do
local playerTemplate = Player.PlayerGui.HeightBar.Frame:FindFirstChild(player.Name)
local Character = game.Workspace[player.Name]
local PrimaryPart = Character:FindFirstChild("HumanoidRootPart")
local Height = math.ceil(PrimaryPart.Position.Y)
playerTemplate.Position = UDim2.new(-1.03, 0, 0.922 - Height / 230, 0)
end
end)
Players.PlayerAdded:Connect(function()
if Player:WaitForChild("PlayerGui") then
local Temp = Player.PlayerGui.HeightBar.Frame.Temp:Clone()
Temp.Name = tostring(Player.Name)
Temp.Parent = Player.PlayerGui.HeightBar.Frame
local Character = game.Workspace[Player.Name]
local PrimaryPart = Character:FindFirstChild("HumanoidRootPart")
local Height = math.ceil(PrimaryPart.Position.Y)
Temp.Position = UDim2.new(-1.03, 0, 0.922 - Height / 230, 0)
for _, player in pairs(game.Players:GetPlayers()) do
local Template = Player.PlayerGui.HeightBar.Frame.Temp:Clone()
Template.Name = player.Name
local Character = game.Workspace[player.Name]
local PrimaryPart = Character:FindFirstChild("HumanoidRootPart")
local Height = math.ceil(PrimaryPart.Position.Y)
Template.Position = UDim2.new(-1.03, 0, 0.922 - Height / 230, 0)
end
end
end)
game.ReplicatedStorage.CreateTemp.OnClientEvent:Connect(function()
local Temp = Player.PlayerGui.HeightBar.Frame.Temp:Clone()
Temp.Name = tostring(Player.Name)
Temp.Parent = Player.PlayerGui.HeightBar.Frame
local Character = game.Workspace[Player.Name]
local PrimaryPart = Character:FindFirstChild("HumanoidRootPart")
local Height = math.ceil(PrimaryPart.Position.Y)
Temp.Position = UDim2.new(-1.03, 0, 0.922 - Height / 230, 0)
end)
You seem to have the general idea down, but you’re repeating a lot of lines and making it much more complicated than it has to be. A general re-write would be good - messy code is never worth it in the long run!
I’m not sure what your general GUI layout is, so here is some code you can tinker with. If you need any clarifications or found any mistakes, feel free to ask.
-- SERVICES
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
-- PRIVATE VARIABLES
local Player = Players.LocalPlayer
local PlayerGui = Player:WaitForChild("PlayerGui")
local HeightBar = PlayerGui:WaitForChild("HeightBar")
local Frame = HeightBar:WaitForChild("Frame") -- probably should rename this, like "PlayerTrackers"?
local TrackerTemplate = Frame:WaitForChild("Temp")
local TrackerList = {}
--------------------------------------------------------------------------------------
-- Tracker functions
-- Remove tracker
local function removeTracker(player)
TrackerList[player]:Destroy()
TrackerList[player] = nil
end
-- Update position of player height trackers
local function updateTracker(player, tracker)
local Character = game.Workspace[player.Name]
local PrimaryPart = Character:FindFirstChild("HumanoidRootPart")
local Height = math.ceil(PrimaryPart.Position.Y)
tracker.Position = UDim2.new(-1.03, 0, 0.922 - Height / 230, 0)
end
-- Create new player height trackers
local function newTracker(player)
local newTracker = TrackerTemplate:Clone()
-- Do whatever you want here to spice up the player's tracker
newTracker.Name = player.Name
-- Add it to the list of trackers
newTracker.Parent = Frame
TrackerList[player] = newTracker
end
--------------------------------------------------------------------------------------
-- Core loop - check every frame to update tracker position
RunService.Heartbeat:Connect(function()
for player, tracker in TrackerList do
updateTracker(player, tracker)
end
end)
-- Listen for players leaving
Players.PlayerRemoving:Connect(function(player)
removeTracker(player)
end)
-- Listen for players being added
Players.PlayerAdded:Connect(function(player)
newTracker(player)
end)
-- Since a player can join after other players
-- Need to first create tracker for every player already present
for _, player in ipairs(Players:GetPlayers()) do
newTracker(player)
end
Quick update, it appears that this doesn’t remove the index from the table. Stumbled across it while doing something else. Just add another line beneath it to remove the index (to prevent memory leaks!)