local Players = game:GetService("Players") local UIS = game:GetService("UserInputService") local RS = game:GetService("RunService") local player = Players.LocalPlayer local playerGui = player:WaitForChild("PlayerGui") local cam = workspace.CurrentCamera local onMobile = not UIS.KeyboardEnabled local keysDown = {} local rotating = false local touchPos = nil local freecamEnabled = false local renderConnection local lockConnection local originalWalkSpeed local originalJumpPower local savedCFrame local currentCharacter if not game:IsLoaded() then game.Loaded:Wait() end local gui = Instance.new("ScreenGui") gui.Name = "MobileFreecamGui" gui.ResetOnSpawn = false gui.IgnoreGuiInset = true gui.DisplayOrder = 999999 gui.Parent = playerGui local button = Instance.new("ImageButton") button.Size = UDim2.new(0,70,0,70) button.Position = UDim2.new(1,-90,0,110) button.BackgroundTransparency = 1 button.Image = "rbxassetid://16803802267" button.ZIndex = 10 button.Parent = gui local inner = Instance.new("ImageLabel") inner.Size = UDim2.new(0.6,0,0.6,0) inner.Position = UDim2.new(0.2,0,0.2,0) inner.BackgroundTransparency = 1 inner.Image = "rbxassetid://127147494935706" inner.ZIndex = 11 inner.Parent = button local speed = 10 local sens = .3 speed /= 10 if onMobile then sens *= 2 end local function startLock(char) currentCharacter = char local hrp = char:WaitForChild("HumanoidRootPart") local humanoid = char:WaitForChild("Humanoid") originalWalkSpeed = humanoid.WalkSpeed originalJumpPower = humanoid.JumpPower humanoid.WalkSpeed = 0 humanoid.JumpPower = 0 savedCFrame = hrp.CFrame if lockConnection then lockConnection:Disconnect() end lockConnection = RS.Heartbeat:Connect(function() if freecamEnabled and hrp.Parent then hrp.CFrame = savedCFrame hrp.AssemblyLinearVelocity = Vector3.zero hrp.AssemblyAngularVelocity = Vector3.zero end end) end local function stopLock() if not currentCharacter then return end local char = currentCharacter local hrp = char:FindFirstChild("HumanoidRootPart") local humanoid = char:FindFirstChild("Humanoid") if lockConnection then lockConnection:Disconnect() lockConnection = nil end if humanoid then humanoid.WalkSpeed = originalWalkSpeed or 16 humanoid.JumpPower = originalJumpPower or 50 end if hrp then hrp.AssemblyLinearVelocity = Vector3.zero hrp.AssemblyAngularVelocity = Vector3.zero end savedCFrame = nil end local function restoreCamera() local char = player.Character if not char then return end local humanoid = char:FindFirstChildOfClass("Humanoid") if not humanoid then return end cam.CameraType = Enum.CameraType.Custom cam.CameraSubject = humanoid end local function renderStepped() if not freecamEnabled then return end if rotating then local delta = UIS:GetMouseDelta() local cf = cam.CFrame local yAngle = cf:ToEulerAngles(Enum.RotationOrder.YZX) local newAmount = math.deg(yAngle)+delta.Y if newAmount > 65 or newAmount < -65 then if not (yAngle<0 and delta.Y<0) and not (yAngle>0 and delta.Y>0) then delta = Vector2.new(delta.X,0) end end cf *= CFrame.Angles(-math.rad(delta.Y),0,0) cf = CFrame.Angles(0,-math.rad(delta.X),0) * (cf - cf.Position) + cf.Position cf = CFrame.lookAt(cf.Position, cf.Position + cf.LookVector) if delta ~= Vector2.new(0,0) then cam.CFrame = cam.CFrame:Lerp(cf,sens) end UIS.MouseBehavior = Enum.MouseBehavior.LockCurrentPosition else UIS.MouseBehavior = Enum.MouseBehavior.Default end if keysDown["Enum.KeyCode.W"] then cam.CFrame *= CFrame.new(0,0,-speed) end if keysDown["Enum.KeyCode.A"] then cam.CFrame *= CFrame.new(-speed,0,0) end if keysDown["Enum.KeyCode.S"] then cam.CFrame *= CFrame.new(0,0,speed) end if keysDown["Enum.KeyCode.D"] then cam.CFrame *= CFrame.new(speed,0,0) end end local validKeys = {"Enum.KeyCode.W","Enum.KeyCode.A","Enum.KeyCode.S","Enum.KeyCode.D"} UIS.InputBegan:Connect(function(Input) if not freecamEnabled then return end for _, key in pairs(validKeys) do if key == tostring(Input.KeyCode) then keysDown[key] = true end end if Input.UserInputType == Enum.UserInputType.MouseButton2 or (Input.UserInputType == Enum.UserInputType.Touch and UIS:GetMouseLocation().X>(cam.ViewportSize.X/2)) then rotating = true end if Input.UserInputType == Enum.UserInputType.Touch then if Input.Position.X < cam.ViewportSize.X/2 then touchPos = Input.Position end end end) UIS.InputEnded:Connect(function(Input) if not freecamEnabled then return end for key,_ in pairs(keysDown) do if key == tostring(Input.KeyCode) then keysDown[key] = false end end if Input.UserInputType == Enum.UserInputType.MouseButton2 or (Input.UserInputType == Enum.UserInputType.Touch and UIS:GetMouseLocation().X>(cam.ViewportSize.X/2)) then rotating = false end if Input.UserInputType == Enum.UserInputType.Touch and touchPos then if Input.Position.X < cam.ViewportSize.X/2 then touchPos = nil keysDown["Enum.KeyCode.W"] = false keysDown["Enum.KeyCode.A"] = false keysDown["Enum.KeyCode.S"] = false keysDown["Enum.KeyCode.D"] = false end end end) UIS.TouchMoved:Connect(function(input) if not freecamEnabled then return end if touchPos then if input.Position.X < cam.ViewportSize.X/2 then if input.Position.Y < touchPos.Y then keysDown["Enum.KeyCode.W"] = true keysDown["Enum.KeyCode.S"] = false else keysDown["Enum.KeyCode.W"] = false keysDown["Enum.KeyCode.S"] = true end if input.Position.X < (touchPos.X-15) then keysDown["Enum.KeyCode.A"] = true keysDown["Enum.KeyCode.D"] = false elseif input.Position.X > (touchPos.X+15) then keysDown["Enum.KeyCode.A"] = false keysDown["Enum.KeyCode.D"] = true else keysDown["Enum.KeyCode.A"] = false keysDown["Enum.KeyCode.D"] = false end end end end) button.MouseButton1Click:Connect(function() freecamEnabled = not freecamEnabled local char = player.Character or player.CharacterAdded:Wait() if freecamEnabled then cam.CameraType = Enum.CameraType.Scriptable startLock(char) renderConnection = RS.RenderStepped:Connect(renderStepped) else stopLock() restoreCamera() if renderConnection then renderConnection:Disconnect() renderConnection = nil end end end) player.CharacterAdded:Connect(function(char) task.wait(0.1) if freecamEnabled then startLock(char) else restoreCamera() end end)