-- Mobile Controls - Left = Move | Right = Look local Players = game:GetService("Players") local UIS = game:GetService("UserInputService") local RunService = game:GetService("RunService") local player = Players.LocalPlayer local cam = workspace.CurrentCamera -- Clean old GUI local function clearOld() local pg = player:FindFirstChild("PlayerGui") if pg and pg:FindFirstChild("MobileVRControls") then pg.MobileVRControls:Destroy() end end clearOld() if not workspace:FindFirstChild("VRPlayers") then warn("Not in VR Hands") return end -- Find Input table (for grabbing) local Input = nil for i = 1, 200 do for _, obj in pairs(getgc(true)) do if type(obj) == "table" and rawget(obj, "rFist") ~= nil and rawget(obj, "lFist") ~= nil then Input = obj break end end if Input then break end task.wait(0.05) end -- Camera control variables (same style as original script) local yaw, pitch = 0, 0 local camPos = cam.CFrame.Position local moveInput = Vector2.zero local lookInput = Vector2.zero do local lv = cam.CFrame.LookVector yaw = math.atan2(-lv.X, -lv.Z) pitch = math.asin(math.clamp(lv.Y, -1, 1)) end -- Create GUI local gui = Instance.new("ScreenGui") gui.Name = "MobileVRControls" gui.ResetOnSpawn = false gui.IgnoreGuiInset = true gui.Parent = player:WaitForChild("PlayerGui") local function makeBtn(text, pos, size, color) local btn = Instance.new("TextButton") btn.Size = size btn.Position = pos btn.BackgroundColor3 = color btn.Text = text btn.TextScaled = true btn.Font = Enum.Font.GothamBold btn.TextColor3 = Color3.new(1,1,1) btn.Parent = gui return btn end -- Joystick creator local function createJoystick(side, position) local bg = Instance.new("Frame") bg.Size = UDim2.new(0.23, 0, 0.23, 0) bg.Position = position bg.BackgroundColor3 = Color3.fromRGB(25, 25, 25) bg.BackgroundTransparency = 0.3 bg.Parent = gui local stick = Instance.new("Frame") stick.Size = UDim2.new(0.42, 0, 0.42, 0) stick.Position = UDim2.new(0.29, 0, 0.29, 0) stick.BackgroundColor3 = Color3.fromRGB(200, 200, 200) stick.Parent = bg local dragging = false local function update(inputPos) local center = bg.AbsolutePosition + bg.AbsoluteSize / 2 local delta = inputPos - center local maxDist = bg.AbsoluteSize.X * 0.38 if delta.Magnitude > maxDist then delta = delta.Unit * maxDist end stick.Position = UDim2.new(0.5, delta.X - stick.AbsoluteSize.X/2, 0.5, delta.Y - stick.AbsoluteSize.Y/2) local x = delta.X / maxDist local y = delta.Y / maxDist if side == "left" then moveInput = Vector2.new(x, -y) -- forward/back + strafe else lookInput = Vector2.new(x, -y) -- look left/right + up/down end end bg.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.Touch or input.UserInputType == Enum.UserInputType.MouseButton1 then dragging = true update(Vector2.new(input.Position.X, input.Position.Y)) end end) UIS.InputChanged:Connect(function(input) if dragging and (input.UserInputType == Enum.UserInputType.Touch or input.UserInputType == Enum.UserInputType.MouseMovement) then update(Vector2.new(input.Position.X, input.Position.Y)) end end) UIS.InputEnded:Connect(function(input) if input.UserInputType == Enum.UserInputType.Touch or input.UserInputType == Enum.UserInputType.MouseButton1 then dragging = false stick.Position = UDim2.new(0.29, 0, 0.29, 0) if side == "left" then moveInput = Vector2.zero else lookInput = Vector2.zero end end end) end -- Create joysticks createJoystick("left", UDim2.new(0.03, 0, 0.67, 0)) -- Move createJoystick("right", UDim2.new(0.74, 0, 0.67, 0)) -- Look -- Buttons local leftTrigger = makeBtn("L Trigger", UDim2.new(0.03, 0, 0.54, 0), UDim2.new(0.17, 0, 0.06, 0), Color3.fromRGB(80, 120, 255)) local rightTrigger = makeBtn("R Trigger", UDim2.new(0.80, 0, 0.54, 0), UDim2.new(0.17, 0, 0.06, 0), Color3.fromRGB(255, 80, 80)) local leftGrip = makeBtn("L Grip", UDim2.new(0.03, 0, 0.47, 0), UDim2.new(0.17, 0, 0.05, 0), Color3.fromRGB(80, 200, 80)) local rightGrip = makeBtn("R Grip", UDim2.new(0.80, 0, 0.47, 0), UDim2.new(0.17, 0, 0.05, 0), Color3.fromRGB(200, 80, 200)) makeBtn("Y", UDim2.new(0.78, 0, 0.38, 0), UDim2.new(0.09, 0, 0.06, 0), Color3.fromRGB(0, 200, 200)) makeBtn("X", UDim2.new(0.70, 0, 0.44, 0), UDim2.new(0.09, 0, 0.06, 0), Color3.fromRGB(200, 200, 0)) makeBtn("A", UDim2.new(0.86, 0, 0.44, 0), UDim2.new(0.09, 0, 0.06, 0), Color3.fromRGB(0, 220, 0)) makeBtn("B", UDim2.new(0.78, 0, 0.50, 0), UDim2.new(0.09, 0, 0.06, 0), Color3.fromRGB(220, 0, 0)) -- Grab buttons if Input then rightTrigger.MouseButton1Down:Connect(function() Input.rFist = 1 Input.rIndex = 1 end) rightTrigger.MouseButton1Up:Connect(function() Input.rFist = 0 Input.rIndex = 0 end) leftTrigger.MouseButton1Down:Connect(function() Input.lFist = 1 Input.lIndex = 1 end) leftTrigger.MouseButton1Up:Connect(function() Input.lFist = 0 Input.lIndex = 0 end) rightGrip.MouseButton1Down:Connect(function() Input.rFist = 1 end) rightGrip.MouseButton1Up:Connect(function() Input.rFist = 0 end) leftGrip.MouseButton1Down:Connect(function() Input.lFist = 1 end) leftGrip.MouseButton1Up:Connect(function() Input.lFist = 0 end) end -- Main control loop (Move + Look) RunService:BindToRenderStep("MobileVR_Control", Enum.RenderPriority.Camera.Value + 2, function(dt) -- Looking yaw = yaw - lookInput.X * 2.8 * dt pitch = math.clamp(pitch + lookInput.Y * 2.2 * dt, -1.4, 1.4) local rot = CFrame.fromEulerAnglesYXZ(pitch, yaw, 0) -- Movement local speed = 28 local move = Vector3.new(moveInput.X, 0, -moveInput.Y) if move.Magnitude > 0 then move = rot:VectorToWorldSpace(move.Unit) * speed * dt camPos = camPos + move end cam.CameraType = Enum.CameraType.Scriptable cam.CFrame = CFrame.new(camPos) * rot end) print("Left = Move | Right = Look loaded")