Rotating a Steering Wheel Bone Around Local Y-Axis in Skeleton3D

Godot Version

v4.3

Question

I’m working on a steering wheel for a bike model using Skeleton3D in Godot 4. The steering wheel is a bone in the armature, and I need to rotate it around its local Y-axis based on user input. However, I’m having issues where the rotation behaves incorrectly because the bone is upside-down.

Setup:

  • The steering wheel is controlled by a bone in the Skeleton3D.
  • I want to set the rotation (not increment it).
  • The bone should rotate smoothly based on input (ui_left, ui_right).
  • Bone index: 10
  • The bone is upside-down, which affects the expected local Y-axis.

Current Code:

extends Node3D

@onready var skeleton: Skeleton3D = $Armature/Skeleton3D

var max_steering_angle: float = 30.0 # Max rotation angle in degrees
var steering_speed: float = 5.0 # Smooth steering speed
var bone_index: int = 10
var current_steering_angle: float = 0.0

func _process(delta: float):
    var input_direction = 0
    
    if Input.is_action_pressed("ui_left"):
        input_direction = 1
    elif Input.is_action_pressed("ui_right"):
        input_direction = -1
    
    # Calculate target steering angle
    var target_angle = input_direction * max_steering_angle
    
    # Smoothly interpolate the steering angle
    current_steering_angle = lerp(current_steering_angle, target_angle, steering_speed * delta)
    
    # Convert to radians
    var angle_radians = deg_to_rad(current_steering_angle)
    
    # Get the bone's global transform
    var bone_global_transform = skeleton.get_bone_global_pose(bone_index)
    
    # Extract the bone's local Y-axis
    var local_y_axis = bone_global_transform.basis.y.normalized()
    
    # Create a quaternion to rotate around the local Y-axis
    var rotation_quaternion = Quaternion(local_y_axis, angle_radians)
    
    # Apply the rotation
    skeleton.set_bone_pose_rotation(bone_index, rotation_quaternion)

Problems I’m Facing:

  1. The steering wheel bone is upside-down, so rotating around Vector3.UP doesn’t work correctly.
  2. The rotation sometimes flips unexpectedly.
  3. I only want to set the rotation, not increment it.
  4. The steering wheel should behave like a real bike handlebar—it should smoothly turn left and right without strange flips.

Questions:

  • How can I correctly rotate the steering wheel bone around its actual local Y-axis?
  • Is Quaternion(local_y_axis, angle_radians) the right approach for this?
  • Should I be using set_bone_pose_rotation(), or is there a better method?
  • Any help would be greatly appreciated!