Cloning a GUI for everybody

Hello! I’ve been recently scripting a spectate menu. However, there is a small issue. In the player menu (players that can be spectated), the Frame that should get cloned for everybody only gets cloned to the targetplayer’s screen. (If their username is Player1, only Player1 will see the new Frame in the menu) Basically they can only see themselves and not other players.

It’s even more weird, as I specifically made a function for that, which should make it possible to get cloned to all players at the same time. As well as other functions, such as destroying for everyone, making something visible for everyone, etcetera.

The script:

local Players = game:GetService("Players")
local Teams = game:GetService("Teams")

local DEBOUNCE = false
local SPECTATE_DEBOUNCE = false

for i, Player in pairs(Players:GetPlayers()) do
	local Gui = Player.PlayerGui:WaitForChild("SpectateMenu")
	local HolderFrame = Gui:WaitForChild("Holder")
	local SpectateButton = HolderFrame:WaitForChild("SpectateButton")
	local PlayerMenu = HolderFrame:WaitForChild("PlayerMenu")
	local ScrollingFrame = PlayerMenu:WaitForChild("ScrollingFrame")
	local Template = ScrollingFrame:WaitForChild("PlayerTemplate")
	local Title = HolderFrame:WaitForChild("Title")
	
	local function spectateButton()
		if Player.Team == Teams.Dead or Player.Team == Teams.Spectators then
			SpectateButton.Visible = true
		elseif Player.Team == Teams.Alive then
			SpectateButton.Visible = false
		end
	end
	
	SpectateButton.MouseButton1Click:Connect(function()
		if SPECTATE_DEBOUNCE == false then
			PlayerMenu.Visible = true
			Title.Visible = true
			HolderFrame.Spectating.Visible = true
			SPECTATE_DEBOUNCE = true
		elseif SPECTATE_DEBOUNCE == true then
			Title.Visible = false
			HolderFrame.Spectating.Visible = false
			PlayerMenu.Visible = false
			SPECTATE_DEBOUNCE = false
		end
	end) 

	Player.CharacterAdded:Connect(spectateButton)
	Player:GetPropertyChangedSignal("Team"):Connect(spectateButton)
	
	Player:GetPropertyChangedSignal("Team"):Connect(function()
		if Player.Team == Teams.Alive then
			local Thumbnail = Players:GetUserThumbnailAsync(Player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size352x352)
			local CloneTemplate = Template:Clone()
			CloneTemplate.Parent = ScrollingFrame
			CloneTemplate.Visible = true
			CloneTemplate.Name = Player.Name
			CloneTemplate.PlayerName.Text = Player.Name
			CloneTemplate.PlayerThumbnail.Image = Thumbnail
			CloneTemplate.PlayerName.MouseButton1Click:Connect(function()
				if DEBOUNCE == false then
					DEBOUNCE = true
					local TargetPlayer = Players:FindFirstChild(tostring(CloneTemplate.Name))
					print("TargetPlayer: "..TargetPlayer.Name)
					HolderFrame.Spectating.Text = "SPECTATING: "..TargetPlayer.Name
					local Camera = workspace.CurrentCamera
					Camera.CameraSubject = TargetPlayer.Character:WaitForChild("Head")
				elseif DEBOUNCE == true then
					local Camera = workspace.CurrentCamera
					Camera.CameraSubject = Player.Character:WaitForChild("Head")
					HolderFrame.Spectating.Text = "SPECTATING: N/A"
					DEBOUNCE = false
				end
			end)
		elseif Player.Team == Teams.Dead or Teams.Spectators then
			local TargetTemplate = Player.PlayerGui:WaitForChild("SpectateMenu"):WaitForChild("Holder"):WaitForChild("PlayerMenu"):WaitForChild("ScrollingFrame"):FindFirstChild(tostring(Player.Name))
			print("before if check")
			if HolderFrame.Spectating.Text == "SPECTATING: "..Player.Name then
				print("after if check")
				print("before destroy on if")
				TargetTemplate:Destroy()
				print("after destroy on if")
				HolderFrame.Spectating.Text = "SPECTATING: N/A"
				local Camera = workspace.CurrentCamera
				Camera.CameraSubject = Player.Character:WaitForChild("Head")
			else
				TargetTemplate:Destroy()
			end
		end
	end)
end

2 Likes

Hello there It seems like you want to create a spectate menu where a player can select another player to spectate , To fix this issue, you should ensure that the Frame gets cloned for all players who open the spectate menu. One way to achieve this is by putting the cloning logic outside of the Player loop.

local Players = game:GetService("Players")
local Teams = game:GetService("Teams")

local SPECTATE_DEBOUNCE = {}

local function setupSpectateMenu(player)
    local Gui = player.PlayerGui:WaitForChild("SpectateMenu")
    local HolderFrame = Gui:WaitForChild("Holder")
    local SpectateButton = HolderFrame:WaitForChild("SpectateButton")
    local PlayerMenu = HolderFrame:WaitForChild("PlayerMenu")
    local ScrollingFrame = PlayerMenu:WaitForChild("ScrollingFrame")
    local Template = ScrollingFrame:WaitForChild("PlayerTemplate")
    local Title = HolderFrame:WaitForChild("Title")

    local function spectateButton()
        if player.Team == Teams.Dead or player.Team == Teams.Spectators then
            SpectateButton.Visible = true
        elseif player.Team == Teams.Alive then
            SpectateButton.Visible = false
        end
    end

    local function handleSpectate(playerName)
        if SPECTATE_DEBOUNCE[player] then
            return
        end
        SPECTATE_DEBOUNCE[player] = true

        HolderFrame.Spectating.Text = "SPECTATING: " .. playerName
        local Camera = workspace.CurrentCamera
        Camera.CameraSubject = Players:FindFirstChild(playerName).Character:WaitForChild("Head")

        -- Reset the debounce after a delay
        wait(2)
        SPECTATE_DEBOUNCE[player] = false
    end

    SpectateButton.MouseButton1Click:Connect(function()
        Title.Visible = not Title.Visible
        HolderFrame.Spectating.Visible = not HolderFrame.Spectating.Visible
        PlayerMenu.Visible = not PlayerMenu.Visible
    end)

    player.CharacterAdded:Connect(spectateButton)
    player:GetPropertyChangedSignal("Team"):Connect(spectateButton)

    player:GetPropertyChangedSignal("Team"):Connect(function()
        if player.Team == Teams.Alive then
            local Thumbnail = Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size352x352)
            local CloneTemplate = Template:Clone()
            CloneTemplate.Parent = ScrollingFrame
            CloneTemplate.Visible = true
            CloneTemplate.Name = player.Name
            CloneTemplate.PlayerName.Text = player.Name
            CloneTemplate.PlayerThumbnail.Image = Thumbnail
            CloneTemplate.PlayerName.MouseButton1Click:Connect(function()
                handleSpectate(player.Name)
            end)
        elseif player.Team == Teams.Dead or player.Team == Teams.Spectators then
            local TargetTemplate = ScrollingFrame:FindFirstChild(player.Name)
            if HolderFrame.Spectating.Text == "SPECTATING: " .. player.Name then
                TargetTemplate:Destroy()
                HolderFrame.Spectating.Text = "SPECTATING: N/A"
                local Camera = workspace.CurrentCamera
                Camera.CameraSubject = player.Character:WaitForChild("Head")
            else
                TargetTemplate:Destroy()
            end
        end
    end)
end

Players.PlayerAdded:Connect(setupSpectateMenu)

1 Like

Thank you for the script, but it doesn’t really help. Now I can’t even open/close the menu, the Frames (Template) don’t get cloned.

I solved this by using RemoteEvents and some extra rework. :wink:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.