class_name FootstepComponent extends Node signal footstep_occured @export var step_measure: float = 1.25 @export var character: CharacterBody3D @export_node_path("AudioStreamPlayer", "AudioStreamPlayer2D", "AudioStreamPlayer3D") var audio_player: NodePath: set = set_audio_player var _distance_traveled: float = 0.0 var _was_in_air: bool = false var _audio_player: Node func _ready() -> void: set_audio_player(audio_player) func _physics_process(delta: float) -> void: # Don't process if it isn't necessary. if not is_instance_valid(character): return if audio_player.is_empty(): return var on_floor: bool = character.is_on_floor() if on_floor: if _was_in_air: # We landed. Play a footstep. play_footstep() _distance_traveled = 0.0 var velocity: Vector3 = abs(character.velocity) velocity.y = 0.0 if velocity.is_zero_approx(): _distance_traveled = 0.0 else: _distance_traveled += velocity.length() * delta if _distance_traveled >= step_measure: _distance_traveled = 0.0 play_footstep() _was_in_air = not on_floor func play_footstep() -> void: footstep_occured.emit() if is_instance_valid(_audio_player) and _audio_player.has_method(&"play"): _audio_player.play() func set_audio_player(new_player_path: NodePath) -> void: audio_player = new_player_path _audio_player = get_node_or_null(new_player_path)