Godot Version
`4.4
Question
` help! my camera script tilts in weird ways at 90 degrees from the starting angle
its all wibble wobbley
extends CharacterBody3D
const SPEED = 10.0
#const JUMP_VELOCITY = 4.5
@onready var neck := $neck
@onready var camera := $neck/Camera3D
func _unhandled_input(event: InputEvent) → void:
if event is InputEventMouseButton:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
elif event.is_action_pressed(“ui_cancel”):
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
if event is InputEventMouseMotion:
neck.rotate_y(-event.relative.x * 0.01)
camera.rotate_x(-event.relative.y * 0.01)
camera.rotation.x = clamp(camera.rotation.x,-PI/2,PI/2)
transform = transform.orthonormalized()
Please format your code properly, as it contains multiple ifs and the indentation is crucial. Use ``` to wrap the code into.
1 Like
best guess is your camera is attached to a character bone and it’s just the neck/head that tilts with the animation.
please give your references types. using := is a way of doing this but in my opinion it’s bad practice. in this particular case, from my side I can’t tell what these nodes are. if neck is for example a bone attachment or similar that would tell me there’s a problem right away.
prefer defining references by dragging the node while holding control, this will give them a definitive type, like:
@onready var camera : Camera3D = $neck/Camera3D
use the godot built-in methods for things like math.
in this case, prefer using deg_to_grad()
to convert degrees to radians for use with clamping.
it is also a good idea to pre-define these values, either with an export
or a const
. you can pre-calculate the values using deg_to_grad
, and you can just type it in the export and it will run in the text field and give you a result immediately.
that said, if I’m not mistaken, this will give you 90º up and down, which is a bad idea. clamping should be lower than 90º, otherwise you will run into gimbal lock, a problem with euler, the method used by godot.
1 Like
Thanks! the neck in the program is a node 3d that the camera is attached to. I made the changes you suggested, but it doesn’t seem to help.
extends CharacterBody3D
const SPEED = 10.0
const maxAngle = deg_to_rad(179)
#const JUMP_VELOCITY = 4.5
@onready var neck : Node3D = $neck
@onready var camera: Camera3D = $neck/Camera3D
func _unhandled_input(event: InputEvent) → void:
if event is InputEventMouseButton:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
elif event.is_action_pressed(“ui_cancel”):
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
if event is InputEventMouseMotion:
neck.rotate_y(-event.relative.x * 0.01)
camera.rotate_x(-event.relative.y * 0.01)
camera.rotation.x = clamp(camera.rotation.x,-maxAngle,maxAngle)
transform = transform.orthonormalized()
func _ready() → void:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _physics_process(delta: float) → void:
var input_dir := Input.get_vector(“ui_left”, “ui_right”, “ui_up”, “ui_down”)
var direction = (neck.transform.basis * Vector3(input_dir.x, 0, input_dir.y))
if direction:
velocity.x = direction.x * SPEED
velocity.z = direction.z * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
velocity.z = move_toward(velocity.z, 0, SPEED)
camera.rotation.z = clamp(camera.rotation.z,0,0)
move_and_slide()