extends CharacterBody3D @export var camera: Camera3D const VIEW_BOB_FREQUENCY = 8 const VIEW_BOB_AMPLITUDE = 0.03 var gravity := 20.0 var speed := 2.0 var turn_speed_sec := 0.1 var turn_degrees := 90 var view_bob_time := 0.0 # increased while velocity is not zero func _get_input() -> Vector3: var input_dir := Vector3() if Input.is_action_pressed("move_forward"): input_dir -= global_transform.basis.z if Input.is_action_pressed("move_backward"): input_dir += global_transform.basis.z return input_dir.normalized() func _process_view_bobbing(delta: float) -> void: view_bob_time += delta * velocity.length() camera.position.y = sin(view_bob_time * VIEW_BOB_FREQUENCY) * VIEW_BOB_AMPLITUDE camera.position.x = cos(view_bob_time * (VIEW_BOB_FREQUENCY / 2)) * VIEW_BOB_AMPLITUDE func _ready() -> void: pass func _unhandled_input(event: InputEvent) -> void: if event.is_action_pressed("turn_left"): create_tween().tween_property( self, "rotation_degrees:y", rotation_degrees.y + turn_degrees, turn_speed_sec ) if event.is_action_pressed("turn_right"): create_tween().tween_property( self, "rotation_degrees:y", rotation_degrees.y - turn_degrees, turn_speed_sec ) func _process(delta: float) -> void: _process_view_bobbing(delta) func _physics_process(delta: float) -> void: velocity.y -= gravity * delta var final_velocity = _get_input() * speed velocity.x = final_velocity.x velocity.z = final_velocity.z move_and_slide()