How to stop function adding more billboard guis than needed?

Whenever a character is added to the game, the server script fires the event then the local script loops through all players creating a billboard gui for each player. Because it does this for each player I then have lots of duplicate guis which are unneccessary. How would I stop this from happening?

Image Example

image

Code

Server Script:

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local individualMute = ReplicatedStorage:WaitForChild("individualMute")

local function onPlayerAdded(player)
	individualMute:FireAllClients(player)
end


Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(onPlayerAdded)
end)

Local Script:

local Players = game:GetService("Players")
local player = Players.LocalPlayer
local playerGui = player.PlayerGui
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local individualMute = ReplicatedStorage:WaitForChild("individualMute")
local muteGui = ReplicatedStorage:WaitForChild("muteGui")
local muteGuiFolder = playerGui:WaitForChild("individualMute")


local function onInduvidualMute()
	wait()
	for i, otherPlayers in pairs(Players:GetChildren()) do
		wait()
		if otherPlayers ~= player then
			wait()
			local muteGuiClone = muteGui:Clone()
			muteGuiClone.Name = otherPlayers.Name
			muteGuiClone.Frame.Visible = true
			muteGuiClone.Parent = muteGuiFolder
			local character = otherPlayers.Character
			if not character or not character.Parent then
				character = player.CharacterAdded:wait()
			end
			muteGuiClone.Adornee = character.UpperTorso
		end
	end
end

individualMute.OnClientEvent:Connect(onInduvidualMute)
1 Like

Can’t you add in a debounce before parenting it to the “muteGuiFolder”

Ok so in your function onPlayerAdded you firing for all clients, which means you will create a new billboard GUI for the new player, and for current ones, you should instead do:

local function onPlayerAdded(player)
	individualMute:FireClient(player)
end

When I do FireClient it gives the error message FireClient: player argument must be a Player object

Change to this:

Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function()
		onPlayerAdded(player)
	end)
end)

You shouldn’t need to fire the event every time a Character gets added to the server, it’s unnecessary just do:

local function onPlayerAdded(player)
    individualMute:FireClient(player)
end

Players.PlayerAdded:Connect(onPlayerAdded)

Maybe he wants to wait the character to load.

in the local script do:

if otherPlayers.PlayerGui.individualMute:FindFirstChild("Player2") then
      print("Cannot clone more!")
else
       Player2:Clone()
end

fireclient breaks the script, it doesnt loop through the players properly leaving some players left without billboard guis assigned to them. I think what I need to do is on the local script find if there is a duplicate it and then destroy the duplicate

@YT_GamingDan

Try this:

Server Script:

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local individualMute = ReplicatedStorage:WaitForChild("individualMute")

local function onPlayerAdded(player)
	individualMute:FireClient(player)
end


Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(onPlayerAdded)
end)

Local Script:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local individualMute = ReplicatedStorage:WaitForChild("individualMute")
local muteGui = ReplicatedStorage:WaitForChild("muteGui")


local function onInduvidualMute(character)
            wait()
            local player = game.Players:GetPlayerFromCharacter(character)
            if player then
			local FoundClone = player.PlayerGui.individualMute:FindFirstChild(player.Name)
			if FoundClone ~= true then
			local muteGuiClone = muteGui:Clone()
			muteGuiClone.Name = player.Name
			muteGuiClone.Frame.Visible = true
			muteGuiClone.Parent = player.PlayerGui.individualMute
			local character = player.Character
			if not character or not character.Parent then
				character = player.CharacterAdded:wait()
			end
		    muteGuiClone.Adornee = character.UpperTorso
	elseif FoundClone ~= false then
		FoundClone:Destroy()
        end
	end
end

individualMute.OnClientEvent:Connect(onInduvidualMute)

I could try that but I dont think it would change anything as the gui will keep on getting cloned when new players join

When using FireClient by doing individualMute:FireClient(player) I get the error message FireClient: player argument must be a Player object. If I use FireClient and if it works it doesn’t loop through the players properly leaving some players left without billboard guis assigned to them.

So, you’ve tried exactly what I sent, and it didn’t work?

yes, I also tried this with a working fireclient in the server script and it seems the local script doesn’t pass through if player then

The following lines of code will activate the onPlayerAdded function that you created above, however, it’ll send the Character through because you’re connecting the CharacterAdded event to the function.

That could be altered to this to send the correct piece of data through:

Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function()
        onPlayerAdded(player)
    end)
end)

However, if you only need it to be activated upon joining, the CharacterAdded part is not needed.

If you have read the LocalScript that I sent, then you will understand that the server script does not need to be changed.

I brought it up as a result of the error message that OP mentioned:

The only time that individualMute:FireClient(player) is used in the Server Script is inside of the onPlayerAdded function.

The error is occurring because the piece of data sent into the onPlayerAdded function is not the player – it sending through the player’s Character because the CharacterAdded event is connected to the function called onPlayerAdded.

I already changed the LocalScript, so it can do the things properly.
The function name does not determine what value is between the ()

The function in the local script is activated with:

individualMute.OnClientEvent:Connect(onInduvidualMute)

I’m aware of what you’re using in the LocalScript, but that part wouldn’t be required since you can reference the LocalPlayer through the Players service in LocalScripts.

The reason I’ve brought up the server script is because the first parameter required when calling :FireClient on a RemoteEvent is a player instance, as outlined by this Developer Hub page. However, when you are activating the function called onPlayerAdded, it is not receiving the player object because CharacterAdded is being connected to the function. This is why the OP pointed out this error message:

Can you define what you mean by stop? Does it create more frames as more join? Do you want it so that it only does it for the player when they join?