class_name PlayerCharacterController extends Node @export var camera: Camera3D = null @export var character: Character = null @export var camera_sensitivity: float = 2.0 @export var camera_lerp_speed: float = 4.0 @export var camera_distance: float = 5.0 @export var camera_min_distance: float = 2.0 @export var camera_max_distance: float = 10.0 @export var camera_pitch: float = -0.5 @export var camera_min_pitch: float = -1.0 @export var camera_max_pitch: float = -0.2 @onready var camera_yaw: float = ( character.global_rotation.y if character else 0.0 ) func _physics_process(delta: float) -> void: if camera && character: var look_input := Vector3( Input.get_axis(&'look_left', &'look_right'), Input.get_axis(&'look_down', &'look_up'), Input.get_axis(&'zoom_in', &'zoom_out') ) camera_distance = clamp( camera_distance + PI*look_input.z*camera_sensitivity*delta, camera_min_distance, camera_max_distance ) camera_yaw = fposmod( camera_yaw - look_input.x*camera_sensitivity*delta, 2.0*PI ) camera_pitch = clamp( camera_pitch + look_input.y*camera_sensitivity*delta, camera_min_pitch, camera_max_pitch ) var bas := Basis.IDENTITY.rotated( Vector3.RIGHT, camera_pitch ).rotated( Vector3.UP, camera_yaw ) bas = Basis.looking_at(-bas.z, character.ground_normal) var posn := character.global_position + camera_distance*bas.z var lerp_weight: float = 1.0 - 0.5**(camera_lerp_speed*delta) camera.global_basis = camera.global_basis.slerp(bas, lerp_weight) camera.global_position = lerp(camera.global_position, posn, lerp_weight) var move_input := Vector2( Input.get_axis(&'move_left', &'move_right'), Input.get_axis(&'move_forward', &'move_backward') ) character.global_impetus = ( move_input.x*camera.basis.x + move_input.y*camera.basis.z ) character.jump_impetus = Input.is_action_pressed(&'jump') character.action1_impetus = Input.is_action_pressed(&'action1') character.action2_impetus = Input.is_action_pressed(&'action2')