Ok, so I am working on a build mode that allows you to build things on pc and on mobile. I have it working perfectly for pc, but it very difficult to figure out how to make it work on mobile. Whenever I move the joystick, it doesn’t move based on the lookvector, but rather the regular x,z,y on roblox studio, I have no idea how to have this work with mobile, and I don’t overly understand camera manipulation that much. It would also be a lot of help if you guys could help me figure out how to zoom with pinching and using the scrolling button on mouse. Thank you for your time!
Code:
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local player = Players.LocalPlayer
local camera = workspace.CurrentCamera
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local cameraBounds = workspace:WaitForChild("ExampleBase")
-- Settings
local cameraSpeed = 1.5
local rotationSpeed = 0.2
local maxY, minY = 50, 1.5
-- State
local freeCamEnabled = false
local cameraCFrame
local yaw, pitch = 0, 0
local lastTouchPosition = nil
local movementKeys = {}
local isRightMouseDown = false
-- Freeze player
local function freezeCharacter()
humanoid.WalkSpeed = 0
humanoid.JumpPower = 0
end
local function unfreezeCharacter()
humanoid.WalkSpeed = 16
humanoid.JumpPower = 50
end
-- Toggle FreeCam using BindableEvent
local toggleEvent = script.Parent.ConnectFly
toggleEvent.Event:Connect(function()
freeCamEnabled = not freeCamEnabled
if freeCamEnabled then
camera.CameraType = Enum.CameraType.Scriptable
cameraCFrame = camera.CFrame
local lookVec = cameraCFrame.LookVector
yaw = math.deg(math.atan2(-lookVec.X, -lookVec.Z))
pitch = math.deg(math.asin(lookVec.Y))
freezeCharacter()
UserInputService.MouseBehavior = Enum.MouseBehavior.Default
else
camera.CameraType = Enum.CameraType.Custom
unfreezeCharacter()
UserInputService.MouseBehavior = Enum.MouseBehavior.Default
end
end)
-- Handle keyboard movement and right mouse button (PC)
UserInputService.InputBegan:Connect(function(input, gameProcessed)
if gameProcessed or not freeCamEnabled then return end
if input.UserInputType == Enum.UserInputType.Keyboard then
movementKeys[input.KeyCode] = true
elseif input.UserInputType == Enum.UserInputType.MouseButton2 then
isRightMouseDown = true
-- Lock mouse *at its current position* on RMB down
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCurrentPosition
end
end)
UserInputService.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.Keyboard then
movementKeys[input.KeyCode] = false
elseif input.UserInputType == Enum.UserInputType.MouseButton2 then
isRightMouseDown = false
-- Release mouse lock on RMB up
UserInputService.MouseBehavior = Enum.MouseBehavior.Default
end
end)
-- Mouse camera rotation (PC)
UserInputService.InputChanged:Connect(function(input)
if not freeCamEnabled then return end
if input.UserInputType == Enum.UserInputType.MouseMovement and isRightMouseDown then
yaw = yaw - input.Delta.X * rotationSpeed
pitch = math.clamp(pitch - input.Delta.Y * rotationSpeed, -89, 89)
end
end)
-- Touch camera rotation (mobile)
UserInputService.TouchMoved:Connect(function(input)
if not freeCamEnabled then return end
if lastTouchPosition then
local delta = input.Position - lastTouchPosition
yaw = yaw - delta.X * rotationSpeed * 0.5
pitch = math.clamp(pitch - delta.Y * rotationSpeed * 0.5, -89, 89)
end
lastTouchPosition = input.Position
end)
UserInputService.TouchEnded:Connect(function()
lastTouchPosition = nil
end)
-- Get movement direction from keyboard or joystick
local function getMoveDirection()
if UserInputService.TouchEnabled or UserInputService.GamepadEnabled then
return humanoid.MoveDirection
end
local direction = Vector3.zero
if movementKeys[Enum.KeyCode.W] then direction += Vector3.new(0, 0, -1) end
if movementKeys[Enum.KeyCode.S] then direction += Vector3.new(0, 0, 1) end
if movementKeys[Enum.KeyCode.A] then direction += Vector3.new(-1, 0, 0) end
if movementKeys[Enum.KeyCode.D] then direction += Vector3.new(1, 0, 0) end
if movementKeys[Enum.KeyCode.E] then direction += Vector3.new(0, 1, 0) end
if movementKeys[Enum.KeyCode.Q] then direction += Vector3.new(0, -1, 0) end
return direction
end
-- Update camera position and rotation
RunService.RenderStepped:Connect(function()
if not freeCamEnabled then return end
-- Rotation
local rotCFrame = CFrame.Angles(0, math.rad(yaw), 0) * CFrame.Angles(math.rad(pitch), 0, 0)
-- Movement
local direction = getMoveDirection()
if direction.Magnitude > 0 then
direction = direction.Unit
local move = (rotCFrame:VectorToWorldSpace(direction)) * cameraSpeed
cameraCFrame = cameraCFrame + move
end
-- Clamp position
local bounds = cameraBounds
local center = bounds.Position
local halfSize = bounds.Size / 2
local pos = cameraCFrame.Position
local clampedX = math.clamp(pos.X, center.X - halfSize.X, center.X + halfSize.X)
local clampedY = math.clamp(pos.Y, minY, maxY)
local clampedZ = math.clamp(pos.Z, center.Z - halfSize.Z, center.Z + halfSize.Z)
cameraCFrame = CFrame.new(Vector3.new(clampedX, clampedY, clampedZ)) * rotCFrame
camera.CFrame = cameraCFrame
end)