Trying To Add Walking Sound Effect

Godot Version 4.2.2

Cant figure out what to do. I want it so when my player walks on the ground a footstep sound plays. This is my script for my player.

extends CharacterBody3D

const NORMAL_SPEED = 3.5
const RUN_SPEED = 5
var speed = NORMAL_SPEED
const JUMP_VELOCITY = 3
const SENSITIVITY = 0.003

# Bob variables
const BOB_FREQ = 1.8
const BOB_AMP = 0.02
var t_bob = 0.0

# fotstep variables
var can_play : bool = true
signal step
# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = 9.0

@onready var head = $Head
@onready var camera = $Head/Camera3D

func _ready():
	Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)

func _unhandled_input(event):
	if event is InputEventMouseMotion:
		head.rotate_y(-event.relative.x * SENSITIVITY)
		camera.rotate_x(-event.relative.y * SENSITIVITY)
		camera.rotation.x = clamp(camera.rotation.x, deg_to_rad(-40), deg_to_rad(60))

func _physics_process(delta):
	# Add the gravity.
	if not is_on_floor():
		velocity.y -= gravity * delta

	# Handle jump.
	if Input.is_action_pressed("jump") and is_on_floor():
		velocity.y = JUMP_VELOCITY

	# Check for run input.
	if Input.is_action_pressed("run"):
		speed = RUN_SPEED
	else:
		speed = NORMAL_SPEED
		
	# Get the input direction and handle the movement/deceleration.
	var input_dir = Input.get_vector("left", "right", "front", "back")
	var direction = (head.transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	if direction:
		velocity.x = direction.x * speed
		velocity.z = direction.z * speed
	else:
		velocity.x = 0.0
		velocity.z = 0.0
		
	# Head bob
	t_bob += delta * velocity.length() * float(is_on_floor())
	camera.transform.origin = _headbob(t_bob)

	move_and_slide()

func _headbob(time) -> Vector3:
	var pos = Vector3.ZERO
	pos.y = sin(time * BOB_FREQ) * BOB_AMP
	
	return pos

I’m not sure how to handle audio players, but assuming you can play and pause a looping audio file, this is what I would do.

In my player scene, I’d add the audio source node, however that works. Sorry, I don’t know.

In my player script, in the physics process function, I would check if the player is on the floor and walking, and store that as a variable. I’d also keep track of the previous state of this variable from the last call of the physics process function. That way, you can track changes. When the player starts walking, start playing the looping sound. When the player stops walking, stop the sound.

I would not reset the audio playback. That way, if the player repeatedly stops and starts walking, the start of your footstep loop isn’t repeated constantly.

This is a very basic solution that sucks a lot. It would probably sound terrible. Here’s a better one:

Set up an audio source that plays a single step sound, or maybe one of a random selection of footsteps.

Set up a timer with a duration apprpriate for the time between steps. Make it repeat and not autostart.

In the player script, do something similar to what I described in the bad solution. When the player starts moving, play a footstep and start the timer. When the player stops, pause and reset the timer, and play a step unless the timer has a passed duration less than some threshold. This prevents a step from playing if you just stepped already, such as if the player repeatedly starts and stops moving.

Connect the timer complete signal to the audio node, such that a footstep plays on completion.

Now if you walk, footsteps will play at regular intervals, and when you stop moving a step sound will play, unless you very recently just stepped.

You could do something slightly different to account for movement speed or sync steps with headbob.

You forgot to emit the step signal