Hello!
I am making a third-person camera, and I was trying to implement a way so holding right click would let you rotate your camera by moving your mouse without moving the cursor, similar to Roblox’s camera.
The script currently saves the mouse position before capturing it whenever you hold right-click, and when let go, makes it visible and warps it back to where it previously was. This works if it’s let go while the mouse isn’t being moved, but when the mouse is still moving, the cursor gets warped to the middle of the screen.
It also seems the Godot 3D viewport suffers the same issue, as it also warps your mouse to the middle when you let go while moving your mouse.
Anyways, is there a better way to implement this or a way to fix it? Or maybe a different way to keep the mouse still?
@export_range(0.0, 1.0) var mouse_sensitivity = 0.01
@export var tilt_limit = deg_to_rad(80)
var rotating = false
var old_mouse_position: Vector2i
func _process(_delta: float) -> void:
if Input.is_action_just_pressed("rotate camera"):
rotating = true
old_mouse_position = get_viewport().get_mouse_position()
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
if Input.is_action_just_released("rotate camera"):
rotating = false
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
DisplayServer.warp_mouse(old_mouse_position)
func _unhandled_input(event : InputEvent) -> void:
if event is InputEventMouseMotion and rotating:
rotation.y -= event.relative.x * mouse_sensitivity
rotation.x -= event.relative.y * mouse_sensitivity
rotation.x = clampf(rotation.x, -tilt_limit, tilt_limit)
You don’t need the _process(), you can do it all in the _unhandled_input(), should be more efficient this way.
I haven’t changed any of the main logic and this code works for me no matter if I move the mouse or let it be still. Does it not work for you? What happens for you?
extends Node3D
@export_range(0.0, 1.0) var mouse_sensitivity = 0.01
@export var tilt_limit = deg_to_rad(80)
var rotating = false
var old_mouse_position: Vector2i
func _unhandled_input(event : InputEvent) -> void:
if event.is_action_pressed("rotate camera"):
rotating = true
old_mouse_position = get_viewport().get_mouse_position()
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
elif event.is_action_released("rotate camera"):
rotating = false
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
DisplayServer.warp_mouse(old_mouse_position)
elif event is InputEventMouseMotion and rotating:
rotation.y -= event.relative.x * mouse_sensitivity
rotation.x -= event.relative.y * mouse_sensitivity
rotation.x = clampf(rotation.x, -tilt_limit, tilt_limit)
This is how it works for me, I don’t see any reason why it should work different for you. Maybe you can try creating a new project to see if it’ll work there to isolate the case?
Are you developing on Windows? It could be a Windows thing then, because I’m testing on Linux.
Maybe try awaiting a frame before warping the mouse? I don’t have any better idea.