local Players = game:GetService("Players") local RunService = game:GetService("RunService") local UserInputService = game:GetService("UserInputService") local player = Players.LocalPlayer local camera = workspace.CurrentCamera local PlayerModule = require(player.PlayerScripts:WaitForChild("PlayerModule")) local Controls = PlayerModule:GetControls() local freecamEnabled = false local currentPos = camera.CFrame.Position local yaw, pitch = 0, 0 local speed = 50 local originalWalkSpeed = 16 local originalJumpPower = 50 -- Force remove any old versions of this UI so there is ONLY ONE if player.PlayerGui:FindFirstChild("CleanFreecamUI") then player.PlayerGui.CleanFreecamUI:Destroy() end local gui = Instance.new("ScreenGui") gui.Name = "CleanFreecamUI" gui.ResetOnSpawn = false gui.IgnoreGuiInset = true gui.Parent = player:WaitForChild("PlayerGui") -- ================= TOP BAR ================= local topBar = Instance.new("Frame") topBar.Size = UDim2.new(0, 140, 0, 45) topBar.Position = UDim2.new(0.5, -70, 0, 25) topBar.BackgroundTransparency = 1 topBar.Parent = gui -- THE ONLY BUTTON (FREECAM TOGGLE) local camBtn = Instance.new("TextButton") camBtn.Size = UDim2.new(1, 0, 1, 0) camBtn.Position = UDim2.new(0, 0, 0, 0) camBtn.BackgroundColor3 = Color3.fromRGB(180, 50, 60) camBtn.TextColor3 = Color3.new(1, 1, 1) camBtn.Text = "Freecam: OFF" camBtn.Font = Enum.Font.FredokaOne camBtn.TextScaled = true camBtn.Parent = topBar Instance.new("UICorner", camBtn).CornerRadius = UDim.new(0.3, 0) local camStroke = Instance.new("UIStroke", camBtn) camStroke.Color = Color3.fromRGB(0,0,0) camStroke.Thickness = 4 -- TELEPORT BUTTON (Hidden until Freecam is ON) local tpBtn = Instance.new("TextButton") tpBtn.Size = UDim2.new(0, 140, 1, 0) tpBtn.Position = UDim2.new(0, 160, 0, 0) tpBtn.BackgroundColor3 = Color3.fromRGB(0, 150, 255) tpBtn.TextColor3 = Color3.new(1, 1, 1) tpBtn.Text = "📍 Teleport" tpBtn.Font = Enum.Font.FredokaOne tpBtn.TextScaled = true tpBtn.Visible = false tpBtn.Parent = topBar Instance.new("UICorner", tpBtn).CornerRadius = UDim.new(0.3, 0) local tpStroke = Instance.new("UIStroke", tpBtn) tpStroke.Color = Color3.fromRGB(0,0,0) tpStroke.Thickness = 4 -- ================= BOTTOM BAR (Speed) ================= local bottomBar = Instance.new("Frame") bottomBar.Size = UDim2.new(0, 250, 0, 40) bottomBar.Position = UDim2.new(0.5, -125, 1, -80) bottomBar.BackgroundColor3 = Color3.fromRGB(40, 40, 40) bottomBar.BackgroundTransparency = 0.1 bottomBar.Visible = false bottomBar.Parent = gui Instance.new("UICorner", bottomBar).CornerRadius = UDim.new(0.5, 0) local speedLabel = Instance.new("TextLabel") speedLabel.Size = UDim2.new(0.6, 0, 1, 0) speedLabel.Position = UDim2.new(0.2, 0, 0, 0) speedLabel.BackgroundTransparency = 1 speedLabel.Text = "Speed: 50" speedLabel.TextColor3 = Color3.new(1, 1, 1) speedLabel.Font = Enum.Font.FredokaOne speedLabel.TextScaled = true speedLabel.Parent = bottomBar local minusBtn = Instance.new("TextButton") minusBtn.Size = UDim2.new(0, 50, 1, 0) minusBtn.Position = UDim2.new(0, 10, 0, 0) minusBtn.BackgroundTransparency = 1 minusBtn.Text = "-" minusBtn.TextColor3 = Color3.fromRGB(255, 100, 100) minusBtn.Font = Enum.Font.FredokaOne minusBtn.TextScaled = true minusBtn.Parent = bottomBar local plusBtn = Instance.new("TextButton") plusBtn.Size = UDim2.new(0, 50, 1, 0) plusBtn.Position = UDim2.new(1, -60, 0, 0) plusBtn.BackgroundTransparency = 1 plusBtn.Text = "+" plusBtn.TextColor3 = Color3.fromRGB(100, 255, 100) plusBtn.Font = Enum.Font.FredokaOne plusBtn.TextScaled = true plusBtn.Parent = bottomBar -- ================= LOGIC ================= camBtn.MouseButton1Click:Connect(function() freecamEnabled = not freecamEnabled if freecamEnabled then camBtn.Text = "Freecam: ON" camBtn.BackgroundColor3 = Color3.fromRGB(50, 180, 50) -- Show Teleport and Speed tpBtn.Visible = true bottomBar.Visible = true -- Expand top bar to fit both buttons topBar.Size = UDim2.new(0, 300, 0, 45) topBar.Position = UDim2.new(0.5, -150, 0, 25) camBtn.Size = UDim2.new(0, 140, 1, 0) -- Setup camera currentPos = camera.CFrame.Position local look = camera.CFrame.LookVector yaw = math.atan2(-look.X, -look.Z) pitch = math.asin(look.Y) camera.CameraType = Enum.CameraType.Scriptable -- Freeze character local char = player.Character if char then local hum = char:FindFirstChildOfClass("Humanoid") if hum then originalWalkSpeed = hum.WalkSpeed originalJumpPower = hum.JumpPower hum.WalkSpeed = 0 hum.JumpPower = 0 end end else camBtn.Text = "Freecam: OFF" camBtn.BackgroundColor3 = Color3.fromRGB(180, 50, 60) -- Hide Teleport and Speed tpBtn.Visible = false bottomBar.Visible = false -- Shrink top bar back to ONE button topBar.Size = UDim2.new(0, 140, 0, 45) topBar.Position = UDim2.new(0.5, -70, 0, 25) camBtn.Size = UDim2.new(1, 0, 1, 0) -- Restore camera camera.CameraType = Enum.CameraType.Custom if player.Character and player.Character:FindFirstChild("HumanoidRootPart") then camera.CFrame = player.Character.HumanoidRootPart.CFrame end -- Unfreeze character local char = player.Character if char then local hum = char:FindFirstChildOfClass("Humanoid") if hum then hum.WalkSpeed = originalWalkSpeed hum.JumpPower = originalJumpPower end end end end) -- Swipe to rotate (Right side of screen) UserInputService.TouchMoved:Connect(function(input, gameProcessed) if freecamEnabled and not gameProcessed then if input.Position.X > camera.ViewportSize.X / 2 then local sens = 0.005 yaw = yaw - input.Delta.X * sens pitch = math.clamp(pitch - input.Delta.Y * sens, -math.rad(89), math.rad(89)) end end end) -- Teleport tpBtn.MouseButton1Click:Connect(function() if freecamEnabled and player.Character then local hrp = player.Character:FindFirstChild("HumanoidRootPart") if hrp then hrp.CFrame = CFrame.new(currentPos + Vector3.new(0, 3, 0)) end end end) -- Speed minusBtn.MouseButton1Click:Connect(function() speed = math.max(10, speed - 10) speedLabel.Text = "Speed: " .. speed end) plusBtn.MouseButton1Click:Connect(function() speed = math.min(200, speed + 10) speedLabel.Text = "Speed: " .. speed end) -- Fly with Joystick RunService.RenderStepped:Connect(function(dt) if freecamEnabled then local rotCF = CFrame.Angles(0, yaw, 0) * CFrame.Angles(pitch, 0, 0) local mv = Controls:GetMoveVector() if mv.Magnitude > 0 then local moveDir = rotCF:VectorToWorldSpace(Vector3.new(mv.X, 0, mv.Z)) currentPos = currentPos + moveDir * speed * dt end camera.CFrame = CFrame.new(currentPos) * rotCF end end)