Godot Version
4.3
Question
Evening! I’m a new dev to godot, working on my first sizable project. What I’m trying to do is make a camera (as well as a flashlight for the camera) that rotates with the mouse - giving sort of a parallax effect that allows the player to only see a specific area in front of them. To do this, I did a simple input function that reads the mouse’s x coordinate when it is moved, then rotates the objects on their Y axis from that point.
func _input(event):
if event is InputEventMouseMotion:
rotate(Vector3.UP, event.relative.x * -0.001)
transform = transform.orthonormalized()
The problem, is that when the mouse is outside the window, or some weird mouse movements happen, the rotation of the camera and the flashlight gets disorented, and starts to rotate to a place it shouldn’t be, or gets misalligned. A way to fix this, I thought, could be to make “limits” for the rotation of the camera and the light, similar to the way that a 2d camera has limits for its movement, but I didn’t know if that would be foolproof or if that would be possible. If anyone could help that would be great.
What mouse mode are you using?
Standard. I would prefer to not lock the player’s mouse in the window as I personally dislike when games do that.
Try clamping the rotation with limits… Maybe that helps.
extends Camera3D # or whatever node you're using
var min_rotation_y = -0.5 # About 30 degrees left
var max_rotation_y = 0.5 # About 30 degrees right
var current_rotation_y = 0.0
func _input(event):
if event is InputEventMouseMotion:
# Add the new rotation value
current_rotation_y += event.relative.x * -0.001
# Clamp the rotation within limits
current_rotation_y = clamp(current_rotation_y, min_rotation_y, max_rotation_y)
# Reset the rotation and apply the clamped value
transform.basis = Basis() # Reset rotation
rotate(Vector3.UP, current_rotation_y)
transform = transform.orthonormalized()
1 Like
Oh my god , thank you so much. I’ve been bashing my head against this for 2 days. This helps a lot. Had no idea clamps existed.
One more thing - when I move the mouse outside of the window, then back in from a different location- like from the top, for example - the camera rotation is in the same place it was, making the mouse movement misaligned. The two ideas i can think for this are making the camera follow the position of the mouse directly and not just basing it on rotation, or making the camera still rotate with the mouse even when it’s outside of the window, but i wouldn’t know how to go about these. Any ideas on how to take care of this? Thanks again for your help.
Just tinkering a bit…
# Configure these values based on your needs
@export var rotation_speed: float = 0.001
@export var min_angle: float = -PI/4 # About -45 degrees
@export var max_angle: float = PI/4 # About 45 degrees
var current_rotation: float = 0.0
func _input(event):
if event is InputEventMouseMotion:
# Update our tracked rotation value
current_rotation -= event.relative.x * rotation_speed
# Clamp the rotation to our limits
current_rotation = clamp(current_rotation, min_angle, max_angle)
# Reset the transform and apply the controlled rotation
transform.basis = Basis() # Reset rotation
rotate(Vector3.UP, current_rotation)
Alright, I made a quick screen recording to show what the problem was a bit better. Decided to just do it in the web editor for simplicity. If you can tell, the issue is that when I move the mouse outside the border and back in, the mouse starts effecting the rotation from the location of the camera - what I would like to happen is to have the camera always be centered on or following the mouse (within the clamps, of course.) So, if I move the mouse out of the window and then back in, the camera should snap to the spot of the mouse.
Should the camera and spotlight be bound toghether ?.. like if you are “walking” in a forest scene ?
1 Like
Sounds like you want to map the absolute position of the mouse to rotation values.
func _input(event: InputEvent) -> void:
if event is InputEventMouseMotion:
rotation.y = remap(event.position.x, 0, VIEWPORT_WIDTH_MAX, min_angle, max_angle)
# After tuning the above values you may want to clamp the angle
rotation.y = clamp(rotation.y, min_angle, max_angle)
1 Like
Tried to do this, sounds like what i should do but when i tried to, the cam is just static. Not sure if i did something wrong?
extends Camera3D
@export var min_angle: float = -PI/4
@export var max_angle: float = PI/4
var viewport_max: float = get_viewport().get_visible_rect().size.x
var base_rotation: float = 0.0
var current_rotation: float = 0.0
func _input(event):
if event is InputEventMouseMotion:
rotation.y = remap(event.position.x, 0, viewport_max, min_angle, max_angle)
# clamp
rotation.y = clamp(rotation.y, min_angle, max_angle)
Sat on it for 20 minutes, then realized that i was being stupid, lmao. Can´t get the viewport size before the viewport exists. 
final code block for reference:
extends Camera3D
@export var min_angle: float = -PI/12
@export var max_angle: float = PI/12
@onready var viewport_max = get_viewport().get_visible_rect().size.x
func _input(event):
if event is InputEventMouseMotion:
rotation.y = remap(event.position.x, viewport_max, 0, min_angle, max_angle)
# clamp
rotation.y = clamp(rotation.y, min_angle, max_angle)
Thank you two, so much, really. This has helped a ton. It felt like godot had everything except for what I needed for this when I was trying it on my own, but I guess you learn every day. Gonna go ahead and mark solution, once again thank you for your help.
1 Like