How do I add sound to walking?

Godot Version

v 4.4

Question

I am trying to add a walking sound to my player. It's a simple top down 2d game with 4-directional movement.I have a simple mp3 that should start playing whenever character is in motion. I am trying to use AudioStreamPlayer node.

What I figure out so far is that the sound receives start( ) every process(second/tick?), so it starts playing from the beginning continuously, resulting in no sound at all. But when the movement stops, the sound continues to play. So everything happens oppositely. I tries using playing( ) attribute, but that didn’t help, it’s like the code is ignoring it.

My code is quite simple, I am trying to avoid using state machine, as my game won’t really have anything besides idle and run modes. I have searched far and wide, but seemingly this simple problem is beyond me. Could someone advice where would I put play( ) and stop( ) for this to work?

All idea would be greatly appreciated.

extends CharacterBody2D

@export var movement_speed : float = 150
var character_direction : Vector2
var last_direction : Vector2 = Vector2.RIGHT
@onready var RunSound: AudioStreamPlayer = $RunSound
@onready var sprite_animation_body: AnimatedSprite2D = $Sprite_animation_body

func _physics_process(_delta: float) → void:
process_movement()
process_animation()
move_and_slide()

func process_movement() → void:
character_direction = Input.get_vector(“move_left”,“move_right”,“move_up”,“move_down”)
character_direction = character_direction.normalized()
if character_direction != Vector2.ZERO:
velocity = character_direction * movement_speed
last_direction = character_direction
else:
velocity = Vector2.ZERO
pass

func process_animation():
var type : String
if velocity != Vector2.ZERO:
type = “run”
else:
type = “idle”
play_animation(type, last_direction)
pass

func play_animation(type: String, direction: Vector2):
if direction.x > 0:
sprite_animation_body.play(type+“right”)
elif direction.x < 0:
sprite_animation_body.play(type+“left”)
elif direction.y > 0:
sprite_animation_body.play(type+“down”)
elif direction.y < 0:
sprite_animation_body.play(type+“up”)
pass

Is your sound a looping sound or a singular step sound?

It’s a loop, I also set it up as a loop when importing.

You could try enabling autostart in AudioStreamPlayer and add this to your _physics_process function:

run_sound.stream_paused = velocity.length() < 1
1 Like

I tried, it didn’t help. I even printed the velocity.length to check what is it. When the character is idle it’s 0 and when he runs it’s 150 as expected, yet code still ignores the condition to stop or pause the sound.

Can you post your entire script again and confirm autostart is enabled on the audio player node.

Please post your code with the correct indentation.

I use a method that fires one footstep sfx and call that method from the animation player at the correct frame(s). This allows footsteps to sync to the anim correctly even when the speed changes.

2 Likes

I’ve seen this approach; I am using AnimatedSprite2d. I haven’t seen anywhere to put sound on individual frames. I hope there is a way to achieve this with my current setup without changing the animations.

I am attaching screenshots of how I set up my AudioStreamPlayer.

Here is the formatted code.

extends CharacterBody2D

@export var movement_speed : float = 150
var character_direction : Vector2
var last_direction : Vector2 = Vector2.RIGHT
@onready var RunSound: AudioStreamPlayer = $RunSound
@onready var sprite_animation_body: AnimatedSprite2D = $Sprite_animation_body

func _physics_process(_delta: float) → void:
	process_movement()
	process_animation()
	move_and_slide()

func process_movement() → void:
	character_direction = Input.get_vector(“move_left”,“move_right”,“move_up”,“move_down”)
	character_direction = character_direction.normalized()
	if character_direction != Vector2.ZERO:
		velocity = character_direction * movement_speed
		last_direction = character_direction
	else:
		velocity = Vector2.ZERO
	pass

func process_animation():
	var type : String
	if velocity != Vector2.ZERO:
		type = “run”
	else:
		type = “idle”
	play_animation(type, last_direction)
	pass

func play_animation(type: String, direction: Vector2):
	if direction.x > 0:
		sprite_animation_body.play(type+“right”)
	elif direction.x < 0:
		sprite_animation_body.play(type+“left”)
	elif direction.y > 0:
		sprite_animation_body.play(type+“down”)
	elif direction.y < 0:
		sprite_animation_body.play(type+“up”)
	pass

Add RunSound.stream_paused = true / RunSound.stream_paused = false where you are changing the animations

AnimatedSprite2D has a signal frame_changed that you can use. Whenever you are on your “step” frame you can play your sound effect.

It worked, thank you a lot. I am not entirely sure if it was because we used stream_paused or the location. Maybe both. I placed it in the process_animation( ). Here is the code.

func process_animation():
var type : String
if velocity != Vector2.ZERO:
type = “run”
RunSound.stream_paused = false
else:
type = “idle”
RunSound.stream_paused = true
play_animation(type, last_direction)
pass

Thanks again.

1 Like