
KeylessUniversal

-- Fly GUI v4 by EricBerpa | Standalone client controller for Roblox R6 and R15.
-- Install as a LocalScript in StarterPlayerScripts, or use the optional loader
-- in a client environment that explicitly provides loadstring and game:HttpGet.
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Workspace = game:GetService("Workspace")
local player = Players.LocalPlayer
assert(player, "Fly GUI must run on the client, not the server.")
local playerGui = player:WaitForChild("PlayerGui", 10)
assert(playerGui, "Fly GUI could not find PlayerGui.")
local CONFIG = {
DefaultSpeed = 50,
MinSpeed = 10,
MaxSpeed = 200,
SpeedStep = 10,
Smoothing = 12,
ToggleKey = Enum.KeyCode.F,
MinimizeKey = Enum.KeyCode.RightShift,
}
local GUI_NAME = "FlyGuiV4"
local CLOSE_EVENT = "Shutdown"
-- Shut down the previous controller before replacing its UI and constraints.
local previous = playerGui:FindFirstChild(GUI_NAME)
if previous then
local shutdown = previous:FindFirstChild(CLOSE_EVENT)
if shutdown and shutdown:IsA("BindableFunction") then
pcall(function() shutdown:Invoke() end)
end
previous:Destroy()
end
local palette = {
Background = Color3.fromRGB(17, 23, 35),
Surface = Color3.fromRGB(29, 38, 53),
Border = Color3.fromRGB(53, 66, 86),
Accent = Color3.fromRGB(94, 234, 212),
Text = Color3.fromRGB(238, 244, 252),
Muted = Color3.fromRGB(161, 177, 198),
Danger = Color3.fromRGB(251, 113, 133),
}
local connections = {}
local flight = nil
local destroyed = false
local minimized = false
local speed = CONFIG.DefaultSpeed
local keys = {}
local holds = {}
local drag = nil
local inputFocused = true
local controller = {}
local function connect(signal, callback)
local connection = signal:Connect(callback)
table.insert(connections, connection)
return connection
end
local function create(className, properties, parent)
local instance = Instance.new(className)
for key, value in pairs(properties) do
instance[key] = value
end
instance.Parent = parent
return instance
end
local function round(instance, radius)
create("UICorner", { CornerRadius = UDim.new(0, radius or 10) }, instance)
end
local gui = create("ScreenGui", {
Name = GUI_NAME,
ResetOnSpawn = false,
ZIndexBehavior = Enum.ZIndexBehavior.Sibling,
DisplayOrder = 20,
}, playerGui)
local shutdown = create("BindableFunction", { Name = CLOSE_EVENT }, gui)
local canvas = create("Frame", {
Name = "Canvas",
Size = UDim2.fromScale(1, 1),
BackgroundTransparency = 1,
BorderSizePixel = 0,
Active = false,
}, gui)
local panel = create("Frame", {
Name = "Panel",
Position = UDim2.fromOffset(24, 120),
Size = UDim2.fromOffset(300, 290),
BackgroundColor3 = palette.Background,
BorderSizePixel = 0,
ClipsDescendants = true,
Active = true,
}, canvas)
round(panel, 14)
create("UIStroke", { Color = palette.Border, Thickness = 1 }, panel)
local function label(parent, name, text, position, size, textSize, color)
return create("TextLabel", {
Name = name,
Position = position,
Size = size,
BackgroundTransparency = 1,
Font = Enum.Font.Gotham,
Text = text,
TextSize = textSize or 14,
TextColor3 = color or palette.Text,
TextXAlignment = Enum.TextXAlignment.Left,
}, parent)
end
local function button(parent, name, text, position, size)
local result = create("TextButton", {
Name = name,
Position = position,
Size = size,
BackgroundColor3 = palette.Surface,
BorderSizePixel = 0,
AutoButtonColor = true,
Font = Enum.Font.GothamMedium,
Text = text,
TextSize = 14,
TextColor3 = palette.Text,
}, parent)
round(result, 8)
return result
end
local header = create("Frame", {
Name = "Header",
Size = UDim2.new(1, -90, 0, 44),
BackgroundTransparency = 1,
Active = true,
}, panel)
label(header, "Title", "FLY / EricBerpa", UDim2.fromOffset(16, 0), UDim2.new(1, -16, 1, 0), 16)
local minimizeButton = button(panel, "Minimize", "-", UDim2.new(1, -78, 0, 8), UDim2.fromOffset(30, 28))
local closeButton = button(panel, "Close", "X", UDim2.new(1, -42, 0, 8), UDim2.fromOffset(30, 28))
closeButton.TextColor3 = palette.Danger
local body = create("Frame", {
Name = "Body",
Position = UDim2.fromOffset(14, 48),
Size = UDim2.new(1, -28, 0, 228),
BackgroundTransparency = 1,
}, panel)
local statusLabel = label(body, "Status", "READY", UDim2.fromOffset(0, 0), UDim2.new(1, 0, 0, 20), 12, palette.Muted)
local toggleButton = button(body, "ToggleFlight", "START FLYING [F]", UDim2.fromOffset(0, 28), UDim2.new(1, 0, 0, 42))
label(body, "SpeedTitle", "SPEED", UDim2.fromOffset(0, 82), UDim2.fromOffset(76, 16), 11, palette.Muted)
local minusButton = button(body, "DecreaseSpeed", "-", UDim2.fromOffset(0, 104), UDim2.fromOffset(42, 36))
local speedLabel = label(body, "SpeedValue", "", UDim2.fromOffset(48, 104), UDim2.new(1, -96, 0, 36), 16)
speedLabel.TextXAlignment = Enum.TextXAlignment.Center
local plusButton = button(body, "IncreaseSpeed", "+", UDim2.new(1, -42, 0, 104), UDim2.fromOffset(42, 36))
local upButton = button(body, "Ascend", "UP / E", UDim2.fromOffset(0, 150), UDim2.new(0.5, -5, 0, 38))
local downButton = button(body, "Descend", "DOWN / Q", UDim2.new(0.5, 5, 0, 150), UDim2.new(0.5, -5, 0, 38))
local help = label(body, "Help", "WASD / joystick to move. Hold UP / DOWN.\nRight Shift: collapse. Drag the header to move.", UDim2.fromOffset(0, 199), UDim2.new(1, 0, 0, 30), 10, palette.Muted)
help.TextWrapped = true
local function refresh(message)
if destroyed then return end
statusLabel.Text = message or (flight and "FLYING" or "READY")
statusLabel.TextColor3 = flight and palette.Accent or palette.Muted
toggleButton.Text = flight and "STOP FLYING [F]" or "START FLYING [F]"
toggleButton.BackgroundColor3 = flight and palette.Accent or palette.Surface
toggleButton.TextColor3 = flight and palette.Background or palette.Text
speedLabel.Text = tostring(speed) .. " studs/s"
minusButton.TextTransparency = speed <= CONFIG.MinSpeed and 0.6 or 0
plusButton.TextTransparency = speed >= CONFIG.MaxSpeed and 0.6 or 0
end
local function clearInput()
table.clear(keys)
table.clear(holds)
drag = nil
end
local function stopFlight(message)
local active = flight
flight = nil
clearInput()
if active then
for _, connection in ipairs(active.Connections) do
connection:Disconnect()
end
for _, instance in ipairs(active.Instances) do
instance:Destroy()
end
local humanoid = active.Humanoid
if humanoid.Parent then
humanoid.AutoRotate = active.AutoRotate
humanoid.PlatformStand = active.PlatformStand
if humanoid.Health > 0 and not active.PlatformStand then
humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
end
end
if active.Root.Parent then
active.Root.AssemblyLinearVelocity = Vector3.zero
active.Root.AssemblyAngularVelocity = Vector3.zero
end
end
refresh(message)
end
local function flatUnit(vector, fallback)
local flat = Vector3.new(vector.X, 0, vector.Z)
return flat.Magnitude > 0.001 and flat.Unit or fallback
end
local function movementDirection(active)
if not inputFocused or UserInputService:GetFocusedTextBox() then
return Vector3.zero
end
local camera = Workspace.CurrentCamera
local x = (keys[Enum.KeyCode.D] and 1 or 0) - (keys[Enum.KeyCode.A] and 1 or 0)
local z = (keys[Enum.KeyCode.W] and 1 or 0) - (keys[Enum.KeyCode.S] and 1 or 0)
local direction
if camera and (x ~= 0 or z ~= 0) then
local right = flatUnit(camera.CFrame.RightVector, Vector3.xAxis)
-- RightVector stays horizontal for a normally controlled camera,
-- so this remains well defined when looking straight up/down.
local forward = Vector3.yAxis:Cross(right)
direction = right * x + forward * z
else
local move = active.Humanoid.MoveDirection
direction = Vector3.new(move.X, 0, move.Z)
end
local up = keys[Enum.KeyCode.E] or keys[Enum.KeyCode.Space]
local down = keys[Enum.KeyCode.Q] or keys[Enum.KeyCode.LeftControl]
for _, value in pairs(holds) do
if value > 0 then up = true else down = true end
end
direction += Vector3.new(0, (up and 1 or 0) - (down and 1 or 0), 0)
-- Preserve joystick strength, while keeping diagonal movement capped.
return direction.Magnitude > 1 and direction.Unit or direction
end
function controller:SetFlying(enabled)
if destroyed then return false end
if not enabled then
stopFlight()
return true
end
if flight then return true end
local character = player.Character
local humanoid = character and character:FindFirstChildOfClass("Humanoid")
local root = character and character:FindFirstChild("HumanoidRootPart")
if not humanoid or not root or not root:IsA("BasePart") or humanoid.Health <= 0 then
refresh("WAITING FOR A LIVING CHARACTER")
return false
end
if root.Anchored or humanoid.Sit then
refresh(root.Anchored and "CHARACTER IS ANCHORED" or "LEAVE YOUR SEAT FIRST")
return false
end
clearInput()
local active = {
Character = character,
Humanoid = humanoid,
Root = root,
AutoRotate = humanoid.AutoRotate,
PlatformStand = humanoid.PlatformStand,
Instances = {},
Connections = {},
Velocity = Vector3.zero,
}
flight = active
local ok, err = pcall(function()
-- Register every object before assigning properties so a failed setup
-- can always remove the objects it created.
local function owned(className)
local instance = Instance.new(className)
table.insert(active.Instances, instance)
return instance
end
local attachment = owned("Attachment")
attachment.Name = "FlyGuiAttachment"
attachment.Parent = root
local velocity = owned("LinearVelocity")
velocity.Name = "FlyGuiVelocity"
velocity.Attachment0 = attachment
velocity.RelativeTo = Enum.ActuatorRelativeTo.World
velocity.VelocityConstraintMode = Enum.VelocityConstraintMode.Vector
velocity.ForceLimitsEnabled = false
velocity.VectorVelocity = Vector3.zero
velocity.Parent = root
local orientation = owned("AlignOrientation")
orientation.Name = "FlyGuiOrientation"
orientation.Attachment0 = attachment
orientation.Mode = Enum.OrientationAlignmentMode.OneAttachment
orientation.MaxTorque = 1000000
orientation.MaxAngularVelocity = 100
orientation.Responsiveness = 25
orientation.CFrame = root.CFrame.Rotation
orientation.Parent = root
humanoid.AutoRotate = false
humanoid.PlatformStand = true
humanoid:ChangeState(Enum.HumanoidStateType.Physics)
table.insert(active.Connections, humanoid.Died:Connect(function()
stopFlight("RESPAWN TO FLY AGAIN")
end))
-- One physics update, independent of speed and frame rate.
table.insert(active.Connections, RunService.PreSimulation:Connect(function(dt)
if flight ~= active then return end
if player.Character ~= character or not root.Parent or not humanoid.Parent
or humanoid.Health <= 0 or root.Anchored or humanoid.Sit
or not attachment.Parent or not velocity.Parent or not orientation.Parent then
stopFlight("FLIGHT STOPPED")
return
end
local target = movementDirection(active) * speed
local alpha = 1 - math.exp(-CONFIG.Smoothing * math.max(dt, 0))
active.Velocity = active.Velocity:Lerp(target, alpha)
velocity.VectorVelocity = active.Velocity
local camera = Workspace.CurrentCamera
if camera then
local facing = flatUnit(camera.CFrame.LookVector,
flatUnit(root.CFrame.LookVector, Vector3.new(0, 0, -1)))
orientation.CFrame = CFrame.lookAt(Vector3.zero, facing)
end
end))
end)
if not ok then
stopFlight("COULD NOT START FLIGHT")
warn("Fly GUI: " .. tostring(err))
return false
end
refresh()
return true
end
function controller:Toggle()
return self:SetFlying(flight == nil)
end
function controller:SetSpeed(value)
if destroyed or type(value) ~= "number" or value ~= value
or value == math.huge or value == -math.huge then
return false
end
speed = math.clamp(math.floor(value + 0.5), CONFIG.MinSpeed, CONFIG.MaxSpeed)
refresh()
return true
end
local function clampPanel()
if destroyed then return end
local available = canvas.AbsoluteSize
if available.X <= 0 or available.Y <= 0 then return end
local width = math.min(300, math.max(1, available.X - 16))
panel.Size = UDim2.fromOffset(width, minimized and 44 or 290)
panel.Position = UDim2.fromOffset(
math.clamp(panel.Position.X.Offset, 0, math.max(0, available.X - width)),
math.clamp(panel.Position.Y.Offset, 0, math.max(0, available.Y - panel.Size.Y.Offset))
)
end
function controller:SetMinimized(value)
if destroyed then return end
minimized = value == true
table.clear(holds)
body.Visible = not minimized
minimizeButton.Text = minimized and "+" or "-"
clampPanel()
end
function controller:GetState()
return { Flying = flight ~= nil, Speed = speed, Minimized = minimized, Destroyed = destroyed }
end
function controller:Destroy()
if destroyed then return end
destroyed = true
stopFlight()
for _, connection in ipairs(connections) do
connection:Disconnect()
end
table.clear(connections)
shutdown.OnInvoke = nil
gui:Destroy()
end
shutdown.OnInvoke = function() controller:Destroy() end
connect(gui.Destroying, function() controller:Destroy() end)
connect(player.CharacterRemoving, function() stopFlight("WAITING FOR CHARACTER") end)
connect(player.CharacterAdded, function() stopFlight("READY - PRESS F TO FLY") end)
connect(toggleButton.Activated, function() controller:Toggle() end)
connect(minusButton.Activated, function() controller:SetSpeed(speed - CONFIG.SpeedStep) end)
connect(plusButton.Activated, function() controller:SetSpeed(speed + CONFIG.SpeedStep) end)
connect(closeButton.Activated, function() controller:Destroy() end)
connect(minimizeButton.Activated, function() controller:SetMinimized(not minimized) end)
connect(canvas:GetPropertyChangedSignal("AbsoluteSize"), clampPanel)
local function isPointer(input)
return input.UserInputType == Enum.UserInputType.MouseButton1
or input.UserInputType == Enum.UserInputType.Touch
end
local function holdButton(target, value)
connect(target.InputBegan, function(input)
if flight and isPointer(input) then holds[input] = value end
end)
connect(target.InputEnded, function(input) holds[input] = nil end)
end
holdButton(upButton, 1)
holdButton(downButton, -1)
connect(header.InputBegan, function(input)
if isPointer(input) then
drag = { Input = input, Start = input.Position, Position = panel.Position }
end
end)
connect(UserInputService.InputChanged, function(input)
if not drag then return end
local touch = drag.Input.UserInputType == Enum.UserInputType.Touch
if (touch and input == drag.Input)
or (not touch and input.UserInputType == Enum.UserInputType.MouseMovement) then
local delta = input.Position - drag.Start
panel.Position = UDim2.fromOffset(drag.Position.X.Offset + delta.X, drag.Position.Y.Offset + delta.Y)
clampPanel()
end
end)
local movementKeys = {
[Enum.KeyCode.W] = true, [Enum.KeyCode.A] = true,
[Enum.KeyCode.S] = true, [Enum.KeyCode.D] = true,
[Enum.KeyCode.E] = true, [Enum.KeyCode.Q] = true,
[Enum.KeyCode.Space] = true, [Enum.KeyCode.LeftControl] = true,
}
connect(UserInputService.InputBegan, function(input, processed)
if processed or not inputFocused or UserInputService:GetFocusedTextBox() then return end
if input.KeyCode == CONFIG.ToggleKey then
controller:Toggle()
elseif input.KeyCode == CONFIG.MinimizeKey then
controller:SetMinimized(not minimized)
elseif movementKeys[input.KeyCode] then
keys[input.KeyCode] = true
end
end)
connect(UserInputService.InputEnded, function(input)
keys[input.KeyCode] = nil
holds[input] = nil
if input.UserInputType == Enum.UserInputType.MouseButton1 then
for pointer in pairs(holds) do
if pointer.UserInputType == Enum.UserInputType.MouseButton1 then holds[pointer] = nil end
end
end
if drag and (input == drag.Input or input.UserInputType == Enum.UserInputType.MouseButton1) then
drag = nil
end
end)
connect(UserInputService.WindowFocusReleased, function()
inputFocused = false
clearInput()
if flight then flight.Velocity = Vector3.zero end
end)
connect(UserInputService.WindowFocused, function() inputFocused = true end)
connect(UserInputService.TextBoxFocused, clearInput)
refresh()
clampPanel()
return controller



Free fly script feel free to edit what u want