Hi, I'm working on my first 3D project. While following this tutorial for a 3D controller from GDQuest, I found some code to extend their camera controls to gamepad. I attached a script to the SpringArm for processing the camera input. I'm using _unhandled_input() to receive the input.

Here's the hierarchy for the nodes in question: Player       |- SpringArm (Script in question)             |- Camera

func _unhandled_input(event: InputEvent) -> void:
	
	if Input.is_action_just_pressed("ui_cancel"):
		Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)

	elif Input.is_action_just_pressed("basic"):
		Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
	
	if event is InputEventJoypadMotion:
		print(event.axis_value)
		yaw = fmod(yaw + (Input.get_action_strength("rs_left") - Input.get_action_strength("rs_right")) * gamepadSens, 360)
		pitch = max(min(pitch + (Input.get_action_strength("rs_up") - Input.get_action_strength("rs_down")) * gamepadSens, 70), -50)
		
		rotation_degrees = Vector3(pitch, yaw, 0)
	
	elif event is InputEventMouseMotion:
		rotation_degrees.x -= event.relative.y * mouseSens
		rotation_degrees.x = clamp(rotation_degrees.x, -90.0, 30.0)
		
		rotation_degrees.y -= event.relative.x * mouseSens
		rotation_degrees.y = wrapf(rotation_degrees.y, 0.0, 360.0)

The trouble I've run into is while the mouse controls work perfectly well, it seems the gamepad motion is only received while the stick is in motion, not when stopped at any point. The intended behavior would be that if I hold left, for example, the camera would continuously move left and only stop once I release the stick.

Should I be using another method? I've tried using _input() but got the same results.

Welcome to the forums @613SPIRAL!

This is intended behavior, as the event is only sent if there is motion on the joystick. What you'll probably want to do to get continuous movement is cache the last motion value of the joystick and then use that in _process or similar to apply the last cached movement each frame:

var right_stick_value = Vector2.ZERO

func _process(delta):
	# if the right stick is pushed a certain distance (may need adjusting)
	if (right_stick_value.length > 0.2):
		yaw = fmod(yaw + right_stick_value.x, 360)
		pitch = max(min(pitch + right_stick_value.y, 70), -50)
		rotation_degrees = Vector3(pitch, yaw, 0)

func _unhandled_input(event):
	if event is InputEventJoypadMotion:
		print(event.axis_value)
		right_joystick_value.x = Input.get_action_strength("rs_left") - Input.get_action_strength("rs_right")
		right_joystick_value.y = Input.get_action_strength("rs_up") - Input.get_action_strength("rs_down")
		right_joystick_value *= gamepadSens

Then if the joystick is held in place, it should still move around as expected :smile:

@TwistedTwigleg said: Welcome to the forums @613SPIRAL!

This is intended behavior, as the event is only sent if there is motion on the joystick. What you'll probably want to do to get continuous movement is cache the last motion value of the joystick and then use that in _process or similar to apply the last cached movement each frame:

var right_stick_value = Vector2.ZERO

func _process(delta):
	# if the right stick is pushed a certain distance (may need adjusting)
	if (right_stick_value.length > 0.2):
		yaw = fmod(yaw + right_stick_value.x, 360)
		pitch = max(min(pitch + right_stick_value.y, 70), -50)
		rotation_degrees = Vector3(pitch, yaw, 0)

func _unhandled_input(event):
	if event is InputEventJoypadMotion:
		print(event.axis_value)
		right_joystick_value.x = Input.get_action_strength("rs_left") - Input.get_action_strength("rs_right")
		right_joystick_value.y = Input.get_action_strength("rs_up") - Input.get_action_strength("rs_down")
		right_joystick_value *= gamepadSens

Then if the joystick is held in place, it should still move around as expected :smile:

Yeah, this works perfectly, thanks for the help!

a year later