
KeylessUniversal

local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local player = Players.LocalPlayer
local camera = workspace.CurrentCamera
-- GUI Setup (bottom-left)
local screenGui = Instance.new("ScreenGui")
screenGui.ResetOnSpawn = false
screenGui.Parent = player:WaitForChild("PlayerGui")
local spectateButton = Instance.new("TextButton")
spectateButton.Size = UDim2.new(0, 120, 0, 40)
spectateButton.Position = UDim2.new(0, 10, 1, -50)
spectateButton.BackgroundColor3 = Color3.fromRGB(40, 40, 40)
spectateButton.TextColor3 = Color3.fromRGB(255, 255, 255)
spectateButton.Text = "Spectate"
spectateButton.Font = Enum.Font.SourceSansBold
spectateButton.TextScaled = true
spectateButton.AutoButtonColor = true
Instance.new("UICorner", spectateButton)
spectateButton.Parent = screenGui
local spectateFrame = Instance.new("Frame")
spectateFrame.Size = UDim2.new(0, 250, 0, 60)
spectateFrame.Position = UDim2.new(0, 10, 1, -120)
spectateFrame.BackgroundColor3 = Color3.fromRGB(25, 25, 25)
spectateFrame.Visible = false
Instance.new("UICorner", spectateFrame)
spectateFrame.Parent = screenGui
local leftArrow = Instance.new("TextButton")
leftArrow.Size = UDim2.new(0, 40, 1, 0)
leftArrow.Position = UDim2.new(0, 0, 0, 0)
leftArrow.BackgroundColor3 = Color3.fromRGB(50, 50, 50)
leftArrow.TextColor3 = Color3.fromRGB(255, 255, 255)
leftArrow.Text = "<"
leftArrow.Font = Enum.Font.SourceSansBold
leftArrow.TextScaled = true
Instance.new("UICorner", leftArrow)
leftArrow.Parent = spectateFrame
local rightArrow = Instance.new("TextButton")
rightArrow.Size = UDim2.new(0, 40, 1, 0)
rightArrow.Position = UDim2.new(1, -40, 0, 0)
rightArrow.BackgroundColor3 = Color3.fromRGB(50, 50, 50)
rightArrow.TextColor3 = Color3.fromRGB(255, 255, 255)
rightArrow.Text = ">"
rightArrow.Font = Enum.Font.SourceSansBold
rightArrow.TextScaled = true
Instance.new("UICorner", rightArrow)
rightArrow.Parent = spectateFrame
local playerNameLabel = Instance.new("TextLabel")
playerNameLabel.Size = UDim2.new(1, -80, 1, 0)
playerNameLabel.Position = UDim2.new(0, 40, 0, 0)
playerNameLabel.BackgroundTransparency = 1
playerNameLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
playerNameLabel.Font = Enum.Font.SourceSansBold
playerNameLabel.TextScaled = true
playerNameLabel.Text = "None"
playerNameLabel.Parent = spectateFrame
-- Teleport Button
local teleportButton = Instance.new("TextButton")
teleportButton.Size = UDim2.new(0, 30, 0, 30)
teleportButton.Position = UDim2.new(1, -35, 1, -35)
teleportButton.BackgroundColor3 = Color3.fromRGB(70, 70, 70)
teleportButton.TextColor3 = Color3.fromRGB(255, 255, 255)
teleportButton.Text = "TP"
teleportButton.Font = Enum.Font.SourceSansBold
teleportButton.TextScaled = true
Instance.new("UICorner", teleportButton)
teleportButton.Parent = spectateFrame
-- Variables
local spectating = false
local currentIndex = 1
local spectatePlayers = {}
-- Update list of players
local function updatePlayerList()
spectatePlayers = {}
for _, plr in ipairs(Players:GetPlayers()) do
if plr ~= player then
table.insert(spectatePlayers, plr)
end
end
end
local function isAlive(target)
return target
and target.Character
and target.Character:FindFirstChild("Humanoid")
and target.Character.Humanoid.Health > 0
end
local function updateNameColor(target)
if target and target.Team ~= player.Team then
playerNameLabel.TextColor3 = Color3.fromRGB(255, 0, 0)
else
playerNameLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
end
end
-- Smooth name animation
local function animateNameChange(newName)
local tweenInfo = TweenInfo.new(0.3, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local fadeOut = TweenService:Create(playerNameLabel, tweenInfo, {TextTransparency = 1})
fadeOut:Play()
fadeOut.Completed:Wait()
playerNameLabel.Text = newName
local fadeIn = TweenService:Create(playerNameLabel, tweenInfo, {TextTransparency = 0})
fadeIn:Play()
end
local function spectate(target)
if isAlive(target) then
camera.CameraSubject = target.Character.Humanoid
camera.CameraType = Enum.CameraType.Custom
animateNameChange(target.Name)
updateNameColor(target)
else
if #spectatePlayers > 0 then
local startIndex = currentIndex
repeat
currentIndex = currentIndex + 1
if currentIndex > #spectatePlayers then currentIndex = 1 end
if currentIndex == startIndex then break end
until isAlive(spectatePlayers[currentIndex])
if isAlive(spectatePlayers[currentIndex]) then
spectate(spectatePlayers[currentIndex])
else
playerNameLabel.Text = "None"
playerNameLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
camera.CameraSubject = player.Character:FindFirstChild("Humanoid")
end
else
playerNameLabel.Text = "None"
playerNameLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
camera.CameraSubject = player.Character:FindFirstChild("Humanoid")
end
end
end
-- Toggle spectate
spectateButton.MouseButton1Click:Connect(function()
spectating = not spectating
spectateFrame.Visible = spectating
updatePlayerList()
if spectating then
if spectatePlayers[currentIndex] and isAlive(spectatePlayers[currentIndex]) then
spectate(spectatePlayers[currentIndex])
else
for i, plr in ipairs(spectatePlayers) do
if isAlive(plr) then
currentIndex = i
spectate(plr)
break
end
end
end
else
if player.Character and player.Character:FindFirstChild("Humanoid") then
camera.CameraSubject = player.Character.Humanoid
end
end
end)
-- Arrow buttons
leftArrow.MouseButton1Click:Connect(function()
if #spectatePlayers > 0 then
repeat
currentIndex = currentIndex - 1
if currentIndex < 1 then currentIndex = #spectatePlayers end
until isAlive(spectatePlayers[currentIndex])
spectate(spectatePlayers[currentIndex])
end
end)
rightArrow.MouseButton1Click:Connect(function()
if #spectatePlayers > 0 then
repeat
currentIndex = currentIndex + 1
if currentIndex > #spectatePlayers then currentIndex = 1 end
until isAlive(spectatePlayers[currentIndex])
spectate(spectatePlayers[currentIndex])
end
end)
-- Teleport
teleportButton.MouseButton1Click:Connect(function()
local target = spectatePlayers[currentIndex]
if target and isAlive(target) and target.Character and target.Character:FindFirstChild("HumanoidRootPart") then
local hrp = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
if hrp then
hrp.CFrame = target.Character.HumanoidRootPart.CFrame + Vector3.new(0,3,0)
end
end
end)
Players.PlayerAdded:Connect(updatePlayerList)
Players.PlayerRemoving:Connect(updatePlayerList)
RunService.RenderStepped:Connect(function()
if spectating and #spectatePlayers > 0 then
if not isAlive(spectatePlayers[currentIndex]) then
spectate(spectatePlayers[currentIndex])
else
updateNameColor(spectatePlayers[currentIndex])
end
end
end)
updatePlayerList()



This script works because it has been tested 7 different times and if you have suggestions then tell me and I can maybe add them
Also this script is free to use no credit needed
tysm man