local Players = game:GetService("Players") local TweenService = game:GetService("TweenService") local LocalPlayer = Players.LocalPlayer local ATTRIBUTE = "SpectateTargetUserId" local gui = Instance.new("ScreenGui") gui.Name = "SpectatorNotifications" gui.ResetOnSpawn = false gui.Parent = LocalPlayer:WaitForChild("PlayerGui") local holder = Instance.new("Frame") holder.BackgroundTransparency = 1 holder.AnchorPoint = Vector2.new(1, 0) holder.Position = UDim2.new(1, -15, 0, 15) holder.Size = UDim2.new(0, 260, 1, -30) holder.Parent = gui local layout = Instance.new("UIListLayout") layout.Padding = UDim.new(0, 6) layout.SortOrder = Enum.SortOrder.LayoutOrder layout.Parent = holder local spectatorLabel = Instance.new("TextLabel") spectatorLabel.Name = "SpectatorsLabel" spectatorLabel.AnchorPoint = Vector2.new(0, 0) spectatorLabel.Position = UDim2.new(0, 15, 0, 15) spectatorLabel.Size = UDim2.new(0, 300, 0, 28) spectatorLabel.BackgroundColor3 = Color3.fromRGB(25, 25, 30) spectatorLabel.BackgroundTransparency = 0.3 spectatorLabel.BorderSizePixel = 0 spectatorLabel.Font = Enum.Font.GothamMedium spectatorLabel.TextSize = 14 spectatorLabel.TextColor3 = Color3.new(1, 1, 1) spectatorLabel.TextXAlignment = Enum.TextXAlignment.Left spectatorLabel.TextTruncate = Enum.TextTruncate.AtEnd spectatorLabel.Text = "Spectators: None" spectatorLabel.Parent = gui Instance.new("UICorner", spectatorLabel).CornerRadius = UDim.new(0, 8) local labelPadding = Instance.new("UIPadding", spectatorLabel) labelPadding.PaddingLeft = UDim.new(0, 10) labelPadding.PaddingRight = UDim.new(0, 10) local order = 0 local function notify(text, color, duration) duration = duration or 3 order += 1 local frame = Instance.new("Frame") frame.LayoutOrder = order frame.Size = UDim2.new(1, 0, 0, 38) frame.BackgroundColor3 = Color3.fromRGB(25, 25, 30) frame.BackgroundTransparency = 1 frame.BorderSizePixel = 0 frame.Parent = holder Instance.new("UICorner", frame).CornerRadius = UDim.new(0, 8) local bar = Instance.new("Frame") -- colored accent on the left bar.Size = UDim2.new(0, 4, 1, 0) bar.BackgroundColor3 = color bar.BackgroundTransparency = 1 bar.BorderSizePixel = 0 bar.Parent = frame Instance.new("UICorner", bar).CornerRadius = UDim.new(0, 8) local label = Instance.new("TextLabel") label.BackgroundTransparency = 1 label.Position = UDim2.new(0, 12, 0, 0) label.Size = UDim2.new(1, -18, 1, 0) label.Font = Enum.Font.GothamMedium label.TextSize = 14 label.TextColor3 = Color3.new(1, 1, 1) label.TextTransparency = 1 label.TextXAlignment = Enum.TextXAlignment.Left label.TextTruncate = Enum.TextTruncate.AtEnd label.Text = text label.Parent = frame local info = TweenInfo.new(0.25, Enum.EasingStyle.Quad, Enum.EasingDirection.Out) TweenService:Create(frame, info, { BackgroundTransparency = 0.15 }):Play() TweenService:Create(bar, info, { BackgroundTransparency = 0 }):Play() TweenService:Create(label, info, { TextTransparency = 0 }):Play() task.delay(duration, function() local out = TweenInfo.new(0.3) TweenService:Create(frame, out, { BackgroundTransparency = 1 }):Play() TweenService:Create(bar, out, { BackgroundTransparency = 1 }):Play() local fade = TweenService:Create(label, out, { TextTransparency = 1 }) fade:Play() fade.Completed:Wait() frame:Destroy() end) end local spectators = {} local function GetSpectators() local names = {} for plr in pairs(spectators) do table.insert(names, plr.Name) end return table.concat(names, ", ") end local function refreshLabel() local names = GetSpectators() spectatorLabel.Text = "Spectators: " .. (names ~= "" and names or "None") end local function updateSpectator(plr) if plr == LocalPlayer then return end local isSpectatingMe = plr:GetAttribute(ATTRIBUTE) == LocalPlayer.UserId if isSpectatingMe and not spectators[plr] then spectators[plr] = true refreshLabel() notify(plr.DisplayName .. " is now spectating you", Color3.fromRGB(80, 200, 120)) elseif not isSpectatingMe and spectators[plr] then spectators[plr] = nil refreshLabel() notify(plr.DisplayName .. " stopped spectating you", Color3.fromRGB(220, 90, 90)) end end local function trackPlayer(plr) if plr == LocalPlayer then return end plr:GetAttributeChangedSignal(ATTRIBUTE):Connect(function() updateSpectator(plr) end) updateSpectator(plr) end for _, plr in ipairs(Players:GetPlayers()) do trackPlayer(plr) end Players.PlayerAdded:Connect(trackPlayer) Players.PlayerRemoving:Connect(function(plr) if spectators[plr] then spectators[plr] = nil refreshLabel() notify(plr.DisplayName .. " left (was spectating you)", Color3.fromRGB(220, 90, 90)) end end)