How to make a Barrel Roll

Godot Version

4.7

Question

Hey there, guys. For my 3D game, I need to make a barrel roll. Whenever the player presses a specifc button, the spaceship should do a barrel roll - just once - and then stop. I honestly have no idea how to make this, the method im using right now just doesn’t work.

func _physics_process(delta: float) -> void:
	const SPEED:float = 5.5
	var input_direction_2D = Input.get_vector(
		"move_left", "move_right", "move_forward", "move_backward"
	)
	var input_direction_3D = Vector3(
		input_direction_2D.x, 0.0, input_direction_2D.y
	)
	
	direction = transform.basis * input_direction_3D
	
	velocity.x = direction.x * SPEED
	velocity.z = direction.z * SPEED
	

	
	
	
	
	#Rotate the player when they're going fast and turning
	if turn_time >= 0.5:
		player_mesh.rotation.z = move_toward(player_mesh.rotation.z, -direction.x, delta * 0.80)
	else:
		player_mesh.rotation.z = move_toward(player_mesh.rotation.z, 0, delta * 0.80)
	
	#Using a sin wave to make the player bob up and down.
	velocity.y = sin(Time.get_ticks_msec() / 500.0) / 4.0 + sin(Time.get_ticks_msec() / 600.0) / 7.0
	
	
	#Checks for specific actions to trigger reactions
	
	#Rotation Stuff
	if Input.is_action_pressed("move_left") or Input.is_action_pressed("move_right"):
		turn_time += delta
		rotation.y += turn_speed if Input.is_action_pressed("move_left") else -turn_speed
		
	if Input.is_action_just_released("move_left") or Input.is_action_just_released("move_right"):
		turn_time = 0.0
	
	#Shooting Mechanics
	if Input.is_action_just_pressed("shoot"):
		shoot_laser()
		
	#Movement Mechanics
	if Input.is_action_pressed("move_up"):
		velocity.y += vertical_velocity 
	elif Input.is_action_pressed("move_down"):
		velocity.y -= vertical_velocity 
	if Input.is_action_just_pressed("barrel_roll"):
		barrel_roll()
	if rotate_for_barrel_roll:
		rotation_degrees.z = move_toward(rotation_degrees.z, 360, 10)
		if abs(rotation_degrees.z) == -360: 
			print("say")
			rotate_for_barrel_roll = false
			
	print(rotation_degrees.z)



func barrel_roll():
	rotate_for_barrel_roll = true

Another problem i have is that my rotation code(the one with turn_time is a bit messed up. These lines:

if turn_time >= 0.5:
		player_mesh.rotation.z = move_toward(player_mesh.rotation.z, -direction.x, delta * 0.80)
	else:
		player_mesh.rotation.z = move_toward(player_mesh.rotation.z, 0, delta * 0.80)
	


#Rotation Stuff
if Input.is_action_pressed("move_left") or Input.is_action_pressed("move_right"):
	turn_time += delta
	rotation.y += turn_speed if Input.is_action_pressed("move_left") else -turn_speed
	
if Input.is_action_just_released("move_left") or Input.is_action_just_released("move_right"):
	turn_time = 0.0

The idea is that when the player holds down the right or left keys for long enough, the spaceship will tilt a little to give more depth. However, since it only rotates around the z axis and doesn’t know what to do when it turns, it’s a bit funky. If anyone knows how to solve either of these, please let me know

Thanks!

One way to handle the z-axis rotation would be to set a roll rate and increase your rotation each frame by that times delta. Mark the roll complete when the accumulated angle is greater than 360. You might be better off basing completion on an angle you compute yourself so that there aren’t problems with Godot’s angle crossing 0.

if Input.is_action_just_pressed("barrel_roll"): # and not rotate_for_barrel_roll?
    barrel_roll()

if rotate_for_barrel_roll:
    roll += roll_rate*delta # used only for testing for completion
    rotation_degrees.z += roll_rate*delta 
    if roll>=360:
        rotate_for_barrel_roll = false
        # could trigger something to move it back toward zero

func barrel_roll():
    roll = 0
    rotate_for_barrel_roll = true

If I understand correctly, you’re trying to use the left & right inputs to actually add the “barrel” to the barrel roll. A way to look at that might be that you’re adding a force component along the x axis. I think if you do that while rotating about z it should push you around the barrel, but I haven’t worked through it. Some y-axis force might be required to tweak to motion.