class_name FootstepsComponent extends Node @export var skeleton: Skeleton3D @export var movement: MovementComponent @export var footsteps: AudioStreamRandomizer @export var step_threshold := 0.1 const feet_names := ["LeftFoot", "RightFoot"] var feet: Array[Foot] = [] func _ready(): for foot_name in feet_names: var foot = Foot.new() foot.bone_name = foot_name foot.bone_id = skeleton.find_bone(foot_name) foot.audio = get_node(foot_name) foot.position = skeleton.to_global(skeleton.get_bone_global_pose(foot.bone_id).origin) foot.attachment = BoneAttachment3D.new() foot.attachment.bone_name = foot_name foot.attachment.bone_idx = foot.bone_id foot.audio.reparent(foot.attachment) skeleton.add_child(foot.attachment) feet.append(foot) func _process(delta: float): for foot in feet: var old_position := foot.position foot.position = skeleton.to_global(skeleton.get_bone_global_pose(foot.bone_id).origin) foot.velocity = (foot.position - old_position) / delta if foot.position.y > step_threshold: continue if foot.velocity.y > 0: continue if foot.velocity.length_squared() < 1.0: continue if foot.audio.playing && foot.audio.get_playback_position() < 0.3: continue play(foot.audio) func play(audio_player: AudioStreamPlayer3D): audio_player.stream = footsteps audio_player.play()