Fly player version - EricBerpa
Key RequiredUniversal

Fly player version - EricBerpa

Universal ScriptEricBerpaEricBerpa 841 views 11.1K executesUpdated Sep 11, 2026
5.0/ 5(3 votes)
30100% Positive
Lua Script•462 lines (17607 chars)
-- 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

Features & Information

Fly + Final Version the best script to fly in every game
#Free#Keyless#Fly

Community Comments (1)

EricBerpaEricBerpaSep 27, 2026

Free fly script feel free to edit what u want

More Scripts for Universal Scripts