Rotating a node every frame
- Edited
Zini So I kind of fixed it by limiting the axes of rotation to one like you said. I look at the mouse movement and if the x movement is bigger I turn horizontally, else I turn vertically. Now this fixed turning horizontally, but vertically, is like a mix between rotating around Z and actually around Y.
func _unhandled_input(event : InputEvent) -> void:
if event is InputEventMouseMotion:
transform = transform.orthonormalized()
if abs(-event.relative.x * SENSITIVITY) > abs(-event.relative.y * SENSITIVITY):
rotate_y(-event.relative.x * SENSITIVITY)
else:
rotate_x(-event.relative.y * SENSITIVITY)
transform = transform.orthonormalized()
As for my solution using two nodes I rotate_y in my rocket scene and send a signal to a child scene which rotate_x's the rocket scene , Scene structure:
rocket(main script)
----MeshInstance3D
----CollisionShape3D
----Camera3D(child script)
main script:
signal rotatex(amount : float)
func _unhandled_input(event : InputEvent) -> void:
if event is InputEventMouseMotion:
rotate_y(-event.relative.x * SENSITIVITY)
rotatex.emit(-event.relative.y * SENSITIVITY)
transform = transform.orthonormalized()
child script:
@onready var parent = get_parent()
func rotatx(amount : float):
parent.rotate_x(amount)
parent.transform = parent.transform.orthonormalized()
If there are syntax errors, they are from typing it here, not in the actual code.
- Edited
There is no need to use a signal. Or to have a script on the child node at all. Also in the child script you manipulate the rotation of the parent, which gets you back to rotating the same node around two axis.
Try replacing
rotatex.emit(-event.relative.y * SENSITIVITY)
with
$Camera3D.rotate_x(-event.relative.y * SENSITIVITY)
Edit: Actually, that would rotate the camera in both direction and the actual model only in one. That is probably not what you want? In this case we need to tweak the node structure more. But its a starting point anyway.
- Edited
No you don't want to rotate a node around two axis. That will never work properly. You want two nodes. Insert a dummy node, if you must. In your case you could insert a Spatial node (or Node3d in Godot 4) above your main node and make that your new main node. Also move the script to that. You rotate your new main node around one axis and your previous main node around the other. Visually the result should be exactly the same as with one node, but without all the problems.
Edit: The problem with two axis on one node is of course only present if you work with Euler rotation. But the alternative is even more complicated: https://docs.godotengine.org/en/stable/tutorials/3d/using_transforms.html. Using two nodes is the way to go here.
If the top level node isn't attached to any nodes that do any transforms of their own you can use the global_transform of the 2nd node (your previous main node) instead of the transform of the new main node.
Rotating a transform around two axis isn't a problem. Using Euler rotation around two axis on a node is. My advice from above should still work on your node structure.