UserInputService:GetMouseDelta() replacement for Xbox joystick

I have an over-the-shoulder camera system, and for the PC I am using GetMouseDelta but I can’t seem to figure out an equivalent. The closet I got was UserInputService.InputChanged() and using input.Position but seemed slightly off directionally.

Here is what I am doing for PC:

maid:GiveTask(RunService.RenderStepped:Connect(function(dt)
		UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
		local delta = UserInputService:GetMouseDelta()
	
		delta *= dt
		yAngle -= delta.X
		xAngle -= delta.Y
		xAngle = math.clamp(xAngle, -1.3, 1.3)

		self._angleTarget = Vector3.new(xAngle, yAngle, 0)
	end))

The mouse delta is calculated by getting the mouse’s position and subtracting it with the mouse’s original position, then setting the original position to the new position afterwards. This should work to get the joystick’s delta:

local ContextActionService = game:GetService("ContextActionService")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")

local delta = Vector3.zero -- delta value starts at zero vector

local position = Vector3.zero -- position value also starts at zero vector

ContextActionService:BindAction("JoystickDelta", function(_, _, inputObject)
	local newPosition = inputObject.Position -- Store the new position in a variable

	delta = newPosition - position -- delta = new position - the position stored in the global variable

	print(delta) -- optional, for debugging purposes

	position = newPosition -- Update the value to the new position
end, false, Enum.KeyCode.Thumbstick2)

maid:GiveTask(RunService.RenderStepped:Connect(function(dt) -- Added the rest of the code as well, to show the recommended location of the code above
	UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
	
	delta *= dt
	yAngle -= delta.X
	xAngle = math.clamp(xAngle - delta.Y, -1.3, 1.3)
	
	self._angleTarget = Vector3.new(xAngle, yAngle, 0)
end))

I tried something similar but didn’t seem to work. The delta was super small and didn’t cause the camera to move

1 Like

We might need to increment a x and y value with the joystick delta multiplied by the loop delta and a speed value. Since the increment will happen inside of a loop, we’ll now need to check for the joystick’s deadzone to make sure the increment doesn’t happen while the joystick is in its resting position:

local ContextActionService = game:GetService("ContextActionService")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")

local SPEED = 10 -- Adjust this value according to your preference
local DEAD = 0.14 -- The joystick deadzone

local delta = Vector3.zero -- delta value starts at zero vector

local position = Vector3.zero -- position value also starts at zero vector

local x, y = 0, 0

local function deadzone(x) -- This is now needed, as the joystick doesn't always rest at 0 like the mouse does
	if math.abs(x) < DEAD then return 0 end
	if x < 0 then return (x + DEAD) / (1 - DEAD) end
	return (x - DEAD) / (1 - DEAD)
end

ContextActionService:BindAction("JoystickDelta", function(_, _, inputObject)
	local newPosition = Vector3.new(deadzone(inputObject.Position.X), deadzone(inputObject.Position.Y), 0) -- Store the new position in a variable

	delta = newPosition - position -- delta = new position - the position stored in the global variable

	print(delta) -- optional, for debugging purposes

	position = newPosition -- Update the value to the new position
end, false, Enum.KeyCode.Thumbstick2)

maid:GiveTask(RunService.RenderStepped:Connect(function(dt) -- Added the rest of the code as well, to show the recommended location of the code above
	UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter

	x += delta.X * dt * SPEED
	y += delta.Y * dt * SPEED

	yAngle -= x
	xAngle = math.clamp(xAngle - y, -1.3, 1.3)

	self._angleTarget = Vector3.new(xAngle, yAngle, 0)
end))