local Players = game:GetService("Players") local RunService = game:GetService("RunService") local UserInputService = game:GetService("UserInputService") local ContextActionService = game:GetService("ContextActionService") local player = Players.LocalPlayer local camera = workspace.CurrentCamera -- ══════════════════════════════════════════ -- CONFIG -- ══════════════════════════════════════════ local TOGGLE_KEY = Enum.KeyCode.F local NORMAL_SPEED = 50 local FAST_SPEED = 150 -- Left Shift local SLOW_SPEED = 15 -- Left Ctrl -- ══════════════════════════════════════════ -- STATE -- ══════════════════════════════════════════ local freecamActive = false local camCFrame = CFrame.new(0, 10, 0) local velocity = Vector3.new() local pitch, yaw = 0, 0 local mouseSensitivity = 0.3 local SMOOTH = 0.15 -- ══════════════════════════════════════════ -- HUD -- ══════════════════════════════════════════ local gui = Instance.new("ScreenGui") gui.Name = "FreecamHUD" gui.ResetOnSpawn = false gui.Parent = player.PlayerGui local label = Instance.new("TextLabel") label.Size = UDim2.new(0, 260, 0, 40) label.Position = UDim2.new(1, -270, 0, 10) label.BackgroundColor3 = Color3.fromRGB(20, 20, 20) label.BackgroundTransparency = 0.2 label.TextColor3 = Color3.fromRGB(255, 80, 80) label.Font = Enum.Font.GothamBold label.TextSize = 14 label.Text = "🔴 Freecam: OFF [F]" label.Parent = gui Instance.new("UICorner", label).CornerRadius = UDim.new(0, 8) local hint = Instance.new("TextLabel") hint.Size = UDim2.new(0, 260, 0, 72) hint.Position = UDim2.new(1, -270, 0, 56) hint.BackgroundColor3 = Color3.fromRGB(20, 20, 20) hint.BackgroundTransparency = 0.4 hint.TextColor3 = Color3.fromRGB(200, 200, 200) hint.Font = Enum.Font.Gotham hint.TextSize = 12 hint.TextXAlignment = Enum.TextXAlignment.Left hint.Text = " WASD — move | Q/E — down/up\n Shift — fast | Ctrl — slow\n Mouse — look" hint.Visible = false hint.Parent = gui Instance.new("UICorner", hint).CornerRadius = UDim.new(0, 8) -- ══════════════════════════════════════════ -- BLOCK CHARACTER MOVEMENT -- Sinks movement inputs at high priority so -- the character controller never receives them -- ══════════════════════════════════════════ local BLOCK_NAME = "FreecamBlockMovement" local MOVEMENT_KEYS = { Enum.KeyCode.W, Enum.KeyCode.A, Enum.KeyCode.S, Enum.KeyCode.D, Enum.KeyCode.Up, Enum.KeyCode.Down, Enum.KeyCode.Left, Enum.KeyCode.Right, Enum.KeyCode.Space, Enum.KeyCode.LeftShift, Enum.KeyCode.LeftControl, } local function blockMovement() ContextActionService:BindActionAtPriority( BLOCK_NAME, function() return Enum.ContextActionResult.Sink end, false, Enum.ContextActionPriority.High.Value, table.unpack(MOVEMENT_KEYS) ) end local function unblockMovement() ContextActionService:UnbindAction(BLOCK_NAME) end -- ══════════════════════════════════════════ -- TOGGLE -- ══════════════════════════════════════════ local savedCameraType local function enableFreecam() freecamActive = true savedCameraType = camera.CameraType camera.CameraType = Enum.CameraType.Scriptable camCFrame = camera.CFrame pitch = -math.asin(math.clamp(camera.CFrame.LookVector.Y, -1, 1)) yaw = math.atan2(-camera.CFrame.LookVector.X, -camera.CFrame.LookVector.Z) velocity = Vector3.new() UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter blockMovement() label.Text = "✅ Freecam: ON [F]" label.TextColor3 = Color3.fromRGB(0, 220, 100) hint.Visible = true end local function disableFreecam() freecamActive = false camera.CameraType = savedCameraType or Enum.CameraType.Custom UserInputService.MouseBehavior = Enum.MouseBehavior.Default unblockMovement() label.Text = "🔴 Freecam: OFF [F]" label.TextColor3 = Color3.fromRGB(255, 80, 80) hint.Visible = false end UserInputService.InputBegan:Connect(function(input, gpe) if gpe then return end if input.KeyCode == TOGGLE_KEY then if freecamActive then disableFreecam() else enableFreecam() end end end) -- ══════════════════════════════════════════ -- MOUSE LOOK -- ══════════════════════════════════════════ UserInputService.InputChanged:Connect(function(input) if not freecamActive then return end if input.UserInputType == Enum.UserInputType.MouseMovement then yaw = yaw - math.rad(input.Delta.X * mouseSensitivity) pitch = math.clamp(pitch - math.rad(input.Delta.Y * mouseSensitivity), math.rad(-89), math.rad(89)) end end) -- ══════════════════════════════════════════ -- RENDER LOOP -- ══════════════════════════════════════════ RunService.RenderStepped:Connect(function(dt) if not freecamActive then return end local speed = NORMAL_SPEED if UserInputService:IsKeyDown(Enum.KeyCode.LeftShift) then speed = FAST_SPEED end if UserInputService:IsKeyDown(Enum.KeyCode.LeftControl) then speed = SLOW_SPEED end local moveDir = Vector3.new() if UserInputService:IsKeyDown(Enum.KeyCode.W) then moveDir += Vector3.new(0, 0, -1) end if UserInputService:IsKeyDown(Enum.KeyCode.S) then moveDir += Vector3.new(0, 0, 1) end if UserInputService:IsKeyDown(Enum.KeyCode.A) then moveDir += Vector3.new(-1, 0, 0) end if UserInputService:IsKeyDown(Enum.KeyCode.D) then moveDir += Vector3.new( 1, 0, 0) end if UserInputService:IsKeyDown(Enum.KeyCode.E) then moveDir += Vector3.new(0, 1, 0) end if UserInputService:IsKeyDown(Enum.KeyCode.Q) then moveDir += Vector3.new(0, -1, 0) end local rotation = CFrame.Angles(0, yaw, 0) * CFrame.Angles(pitch, 0, 0) local worldMove = rotation:VectorToWorldSpace(moveDir) if worldMove.Magnitude > 0 then worldMove = worldMove.Unit * speed * dt end velocity = velocity:Lerp(worldMove, 1 - SMOOTH) camCFrame = CFrame.new(camCFrame.Position + velocity) * rotation camera.CFrame = camCFrame end)