local UIS = game:GetService("UserInputService") local RS = game:GetService("RunService") local Players = game:GetService("Players") local player = Players.LocalPlayer local char = player.Character or player.CharacterAdded:Wait() local root = char:WaitForChild("HumanoidRootPart") local humanoid = char:WaitForChild("Humanoid") local velocityControl = Instance.new("BodyVelocity") velocityControl.MaxForce = Vector3.new(1e5, 0, 1e5) velocityControl.Velocity = Vector3.zero velocityControl.P = 10000 velocityControl.Name = "JoystickVelocity" local speed = 150 local enabled = false local inputVector = Vector3.zero local currentVelocity = Vector3.zero local lerpSpeed = 5 local bodyFollowEnabled = false local lockYEnabled = false local upHeld = false local downHeld = false local lastLookDir = Vector3.new(0, 0, -1) local ySpeed = 50 local ySpeedMultiplier = 1 local gui = Instance.new("ScreenGui", player:WaitForChild("PlayerGui")) gui.Name = "VelocityGui" gui.ResetOnSpawn = false local btn = Instance.new("TextButton") btn.Text = "Velocity: OFF" btn.Size = UDim2.new(0, 140, 0, 50) btn.Position = UDim2.new(0, 10, 0, 10) btn.BackgroundColor3 = Color3.fromRGB(30, 30, 30) btn.TextColor3 = Color3.new(1, 1, 1) btn.Parent = gui btn.MouseButton1Click:Connect(function() enabled = not enabled btn.Text = "Velocity: " .. (enabled and "ON" or "OFF") if enabled then velocityControl.Parent = root else velocityControl.Parent = nil velocityControl.Velocity = Vector3.zero currentVelocity = Vector3.zero upHeld = false downHeld = false end end) local function createBtn(text, posY, isRightSide) local b = Instance.new("TextButton") b.Size = UDim2.new(0, 140, 0, 40) if isRightSide then b.Position = UDim2.new(1, -150, 0, posY) else b.Position = UDim2.new(0, 10, 0, posY) end b.AnchorPoint = Vector2.new(0, 0) b.Text = text b.BackgroundColor3 = Color3.fromRGB(40, 40, 40) b.TextColor3 = Color3.new(1, 1, 1) b.AutoButtonColor = false b.Parent = gui return b end local bodyFollowBtn = createBtn("Body Follow: OFF", 10, true) local lockYBtn = createBtn("Lock Y: OFF", 60, true) local upBtn = createBtn("↑", 110, true) local downBtn = createBtn("↓", 160, true) local ySpeedDownBtn = createBtn("Y Speed -", 210, true) local ySpeedUpBtn = createBtn("Y Speed +", 260, true) bodyFollowBtn.MouseButton1Click:Connect(function() bodyFollowEnabled = not bodyFollowEnabled bodyFollowBtn.Text = "Body Follow: " .. (bodyFollowEnabled and "ON" or "OFF") end) lockYBtn.MouseButton1Click:Connect(function() lockYEnabled = not lockYEnabled lockYBtn.Text = "Lock Y: " .. (lockYEnabled and "ON" or "OFF") end) upBtn.MouseButton1Down:Connect(function() upHeld = true end) upBtn.MouseButton1Up:Connect(function() upHeld = false end) downBtn.MouseButton1Down:Connect(function() downHeld = true end) downBtn.MouseButton1Up:Connect(function() downHeld = false end) ySpeedDownBtn.MouseButton1Click:Connect(function() ySpeedMultiplier = math.max(0.1, ySpeedMultiplier - 0.1) end) ySpeedUpBtn.MouseButton1Click:Connect(function() ySpeedMultiplier = math.min(2.0, ySpeedMultiplier + 0.1) end) local joystickTouch = nil local joystickStartPos = nil UIS.TouchStarted:Connect(function(input) if enabled and not joystickTouch then local screenSize = workspace.CurrentCamera.ViewportSize if input.Position.X < screenSize.X / 2 then joystickTouch = input joystickStartPos = input.Position end end end) UIS.TouchMoved:Connect(function(input) if enabled and input == joystickTouch then local delta = input.Position - joystickStartPos local maxRadius = 100 if delta.Magnitude > maxRadius then delta = delta.Unit * maxRadius end inputVector = Vector3.new(delta.X / maxRadius, 0, delta.Y / maxRadius) end end) UIS.TouchEnded:Connect(function(input) if enabled and input == joystickTouch then joystickTouch = nil inputVector = Vector3.zero end end) local camera = workspace.CurrentCamera camera.CameraType = Enum.CameraType.Custom local function updateCamera() local character = player.Character if not character then return end local rootPart = character:FindFirstChild("HumanoidRootPart") if not rootPart then return end camera.CameraSubject = character:FindFirstChildOfClass("Humanoid") or rootPart camera.CameraType = Enum.CameraType.Custom end player.CharacterAdded:Connect(function() task.wait(0.1) char = player.Character root = char:WaitForChild("HumanoidRootPart") humanoid = char:WaitForChild("Humanoid") updateCamera() end) updateCamera() RS.RenderStepped:Connect(function(dt) if char and root and humanoid then if enabled then local camCF = camera.CFrame local camRight = Vector3.new(camCF.RightVector.X, 0, camCF.RightVector.Z).Unit local camForward = Vector3.new(camCF.LookVector.X, 0, camCF.LookVector.Z).Unit local moveDir = Vector3.zero if inputVector.Magnitude > 0.1 then moveDir = (camRight * inputVector.X + camForward * -inputVector.Z).Unit local targetVelocity = moveDir * speed * inputVector.Magnitude currentVelocity = currentVelocity:Lerp(targetVelocity, math.clamp(lerpSpeed * dt, 0, 1)) if bodyFollowEnabled then lastLookDir = lastLookDir:Lerp(moveDir, math.clamp(lerpSpeed * dt, 0, 1)) root.CFrame = CFrame.lookAt(root.Position, root.Position + lastLookDir) end else currentVelocity = currentVelocity:Lerp(Vector3.zero, math.clamp(lerpSpeed * dt, 0, 1)) end local finalYVelocity = 0 if upHeld then finalYVelocity = ySpeed * ySpeedMultiplier elseif downHeld then finalYVelocity = -ySpeed * ySpeedMultiplier elseif lockYEnabled then finalYVelocity = 0 end if lockYEnabled or upHeld or downHeld then velocityControl.MaxForce = Vector3.new(1e9, 1e9, 1e9) velocityControl.Velocity = Vector3.new(currentVelocity.X, finalYVelocity, currentVelocity.Z) else velocityControl.MaxForce = Vector3.new(1e9, 0, 1e9) velocityControl.Velocity = Vector3.new(currentVelocity.X, 0, currentVelocity.Z) end else velocityControl.Velocity = Vector3.zero end end end)