How do I rotate a 3d object around its local axis with absolute angle value?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By al1f

I have a sword with local x, y and z axes. (blade of sword is local y, right half of handle is local x):

When running my game, the sword blade is facing up, and I need the sword to rotate against its local z axis based on the “ui_left”, “ui_right”, “ui_down” and “ui_up” vector, like so: enter image description here I can use rotate_object_local(Vector3.BACK, radians) to rotate it about the local z axis, but the angle provided needs to be a relative value, whereas the direction I get from direction.angle() is absolute. How do I rotate the sword around its local axis when I have an absolute angle value?

:bust_in_silhouette: Reply From: ld2studio

Node3D’s rotation() and rotation_degree() methods allow you to rotate your sword by an absolute value.

Example:

func _process(delta: float) -> void:
	if Input.is_action_just_pressed("ui_left"):
		$Sword.rotation_degrees.z = 170
	if Input.is_action_just_pressed("ui_right"):
		$Sword.rotation_degrees.z = 10
	if Input.is_action_just_pressed("ui_up"):
		$Sword.rotation_degrees.z = 70
	if Input.is_action_just_pressed("ui_down"):
		$Sword.rotation_degrees.z = -70

I need the sword to rotate around its local axis, not the global axis.
For example, here’s what the sword rotating around the y axis looks like:
-|-------

-|--

+

---|-

-------|-

It works up until the point when I move or transform the sword somewhere else.
This is what that looks like:

    /
   /
  /
-/<

 |
 |
 |
-+<
 |

 \
  \
   \
   -\<

What I want however, is the sword rotating around it’s local axis, just like I can use transform.basis to get the local x, y and z directions.

        /
       /
      /
    -/<

        /
       /
    -+<

        <
    -+<

    -+<--

    -+<
       >

    -+<
      \
       \

    -+<
    /
   / 
  /

al1f | 2023-06-18 23:39

you can make your sword node the child of another node3d called Pivot in this case. This node is used to move the weapon in global space, while the sword node is moved in its local space with rotation().

Pivot
|
-> Sword

Example:

func _process(delta: float) -> void:
	if Input.is_action_just_pressed("ui_left"):
		$Pivot/Sword.rotation_degrees.z = 170

ld2studio | 2023-06-19 05:26

It’s a bit unintuitive but it works. I still run into issues with rotation sometimes though.

al1f | 2023-06-20 09:14