toggling mouse camera control with keybind


i have a 3d first person game where i want to make so that mouse-camera control can be toggled on and off with a key, as to allow you to use the cursor to interact with other things.

in short: if i press tab i want the camera to move like in a regular FPS, and if i press it again i want the camera to stay pointing where it was last, and for the mouse cursor to show up on screen and move freely; i tried doing it myself to very little success.

how would i go about doing that? i’m extremely new to game-making as a whole but i do have some previous programming experience. any help is appreciated.

I assume you know how to capture the mouse otherwise you wouldn’t be in this scenario.

Basically the tab button will capture and uncapture the mouse. But you also have to check if mouse is captured before you do your movement.

If Input.mouse_mode == Input.MouseMode.MOUSE_MODE_CAPTURED:
  #do playerninput

You can implement an action and toggle states like this:

func _unhandled_input(event):
	if Input.is_action_just_pressed("mouse_capture_mode_toggle"):
		if mouse_mode == Input.MOUSE_MODE_VISIBLE: Input.mouse_mode = Input.MOUSE_MODE_CONFINED; 
		elif mouse_mode == Input.MOUSE_MODE_CONFINED: Input.mouse_mode = Input.MOUSE_MODE_CAPTURED;
		else: Input.mouse_mode = Input.MOUSE_MODE_VISIBLE; 

This example loops through 3 states, but you only need two in your case. About the camera, it depends on how exactly you want it to behave. I think the easiest would be to create a second camera, change its position, rotation and so on in the toggle and use camera.make_current() to enable it. Switching back would be as simple as making the one with the player current like $Player/SpringArm3D/Camera3D.make_current() or so. This way your second camera does not move with your player character and you do not have to reparent the one on the player, that I guess you have.

Using Input.is_action_just_pressed in _unhandled_input is in most cases not a good advice (see is_action_just_pressed docs).
Instead access the event directly.

if event.is_action_pressed("mouse_capture_mode_toggle"):
1 Like

But you have to keep in mind that “action_pressed” can trigger multiple times.