Godot Version
4.2.1
Question
I am trying to program a simple airplane simulation. I followed the following tutorial:
https://kidscancode.org/godot_recipes/3.x/3d/simple_airplane/index.html
I have made changes to it in order to be compatible with 4.2.1, the version I am using.
I have a CharacterBody3D with a mesh child and a collision shape child. My script is attached to the CharacterBody3D.
When I accelerate and immediately try to fly straight up everything works as normal. However, if I move left or right, and then attempt to fly straight up, the plane begins spinning along its local z axis. I have mulled over this for a while and all I have been able to figure out is that for some reason, rotation.z does not fully reach 0 on line 66. Instead it simply reaches an extremely low float value (e.g. 0.000233556). Is there some quirk about rotation or the engine that I don’t know?
Here is my code:
extends CharacterBody3D
@export_category("Maximums")
# Can't fly below this speed
@export var min_flight_speed = 10.0
# Maximum airspeed
@export var max_flight_speed = 30.0
@export_category("Speed")
# Turn rate
@export var turn_speed = 0.75
# Climb/dive rate
@export var pitch_speed = 0.5
# Wings "autolevel" speed
@export var level_speed = 3
@export_category("Acceleration and deceleration")
# Throttle change speed
@export var throttle_delta = 30.0
# Acceleration/deceleration
@export var accelertation = 6.0
@export_category("Mesh")
@export var plane_mesh: MeshInstance3D
# Current speed
var forward_speed = 0.0
# Throttle input speed
var target_speed = 0.0
# Lets us change behavior when grounded
var grounded = false
var turn_input = 0.0
var pitch_input = 0.0
func get_input(delta):
# Throttle input
if Input.is_action_pressed("throttle_up"):
target_speed = min(forward_speed + throttle_delta * delta, max_flight_speed)
if Input.is_action_pressed("throttle_down"):
var limit = 0.0 if grounded else min_flight_speed
target_speed = max(forward_speed - throttle_delta * delta, limit)
# Turn (roll/yaw) input
turn_input = 0.0
if forward_speed > 0.5:
turn_input -= Input.get_action_strength("roll_right")
turn_input += Input.get_action_strength("roll_left")
# Pitch (climb/dive) input
pitch_input = 0.0
if not grounded:
pitch_input -= Input.get_action_strength("pitch_up")
if forward_speed >= min_flight_speed:
pitch_input += Input.get_action_strength("pitch_down")
func _physics_process(delta: float) -> void:
get_input(delta)
transform.basis = transform.basis.rotated(transform.basis.x, pitch_input * pitch_speed * delta)
transform.basis = transform.basis.rotated(Vector3.UP, turn_input * turn_speed * delta)
print(rotation.z)
if grounded:
rotation.z = 0
else:
rotation.z = move_toward(rotation.z, turn_input, level_speed * delta)
# Accelerate/decelerate
forward_speed = lerp(forward_speed, target_speed, accelertation * delta)
# Movement is always forward
velocity = -transform.basis.z * forward_speed
if is_on_floor():
if not grounded:
rotation.x = 0
velocity.y -= 1
grounded = true
else:
grounded = false
move_and_slide()
Please let me know if I need to provide any other resources. This is my first time posting here.
Thanks in advance!