The footstep sounds just play continuosly.

I tried different methods to add footstep sounds, but they all just played continuously without even finishing. I’m going to past all of my code for the better view.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MovementScript : MonoBehaviour
{
    [Header("Movement")]
    private CharacterController controller;
    [SerializeField] private float moveSpeed;
    [SerializeField] private float walkSpeed;
    [SerializeField] private float runSpeed;

    public bool isMoving;
    AudioSource playSound;

    [Header("AudioClips")]
    [SerializeField] FootStepGenerator stepGenerator;
    [SerializeField] float footStepTimer;

    Vector3 moveDirection;
    private Vector3 velocity;

    [Header("GroundCheck")]
    [SerializeField] private bool isGrounded;
    [SerializeField] private float groundCheckDistance;
    [SerializeField] private LayerMask groundMask;
    [SerializeField] private float gravity;

    [Header("Crouching")]
    [SerializeField] private float crouchHeight = 0.5f;
    [SerializeField] private float standingHeight = 8f;
    [SerializeField] private float timeToCrouch = 0.5f;
    [SerializeField] private Vector3 crouchingCenter = new Vector3(0, 5, 0);
    [SerializeField] private Vector3 standingCenter = new Vector3(0, 0, 0);
    [SerializeField] private KeyCode crouchKey = KeyCode.C;
    [SerializeField] private bool canCrouch = true;
    private bool isCrouching;
    private bool duringCrouchAnimation;
    private bool ShouldCrouch => Input.GetKeyDown(crouchKey) && !duringCrouchAnimation;


    void Start()
    {
        controller = GetComponent<CharacterController>();
        playSound = GetComponent<AudioSource>();
        isMoving = false;
        stepGenerator = GetComponent<FootStepGenerator>();
    }

   
    void Update()
    {
        Move();
        if (canCrouch)
            HandleCrouch();
    }

    private void HandleCrouch()
    {
        if(ShouldCrouch) StartCoroutine(CrouchStand());
    }

    private IEnumerator CrouchStand()
    {
        duringCrouchAnimation = true;

        float timeElapsed = 0;
        float targetHeight = isCrouching ? standingHeight : crouchHeight;
        float currentHeight = controller.height;
        Vector3 targetCenter = isCrouching ? standingCenter : crouchingCenter;
        Vector3 currentCenter = controller.center;

        while(timeElapsed < timeToCrouch)
        {
            controller.height = Mathf.Lerp(currentHeight, targetHeight, timeElapsed/timeToCrouch);
            controller.center = Vector3.Lerp(currentCenter, targetCenter, timeElapsed/timeToCrouch);
            timeElapsed += Time.deltaTime;
            yield return null;
        }

        controller.height = targetHeight;
        controller.center = targetCenter;

        isCrouching = !isCrouching;

        duringCrouchAnimation = false;
    }
    private void Move()
    {
        isGrounded = Physics.CheckSphere(transform.position, groundCheckDistance, groundMask);
        if (isGrounded && velocity.y < 0)
        {
            velocity.y = -2f;
        }

        float moveZ = Input.GetAxis("Vertical");
        float moveX = Input.GetAxis("Horizontal");

        moveDirection = transform.right * moveX + transform.forward * moveZ;

        if (moveDirection != Vector3.zero && !Input.GetKey(KeyCode.LeftShift))
        {
            isMoving = true;
            moveSpeed = walkSpeed;
        }
        else if (moveDirection != Vector3.zero && Input.GetKey(KeyCode.LeftShift))
        {
            isMoving = true;
            moveSpeed = runSpeed;
        }
        else if(moveDirection == Vector3.zero) isMoving = false;

        if (velocity.x < 0 || velocity.x > 0 || velocity.y > 0 || velocity.y < 0 || velocity.z > 0 || velocity.z < 0)
            if (isMoving) PlayFootSounds();

        controller.Move(moveDirection * Time.deltaTime * moveSpeed);

        velocity.y += gravity * Time.deltaTime;
        controller.Move(velocity * Time.deltaTime);
    }

    void PlayFootSounds()
    {
        StartCoroutine("PlayStepSound", footStepTimer);
    }

    IEnumerator PlayStepSound(float timer)
    {
        var randomIndex = Random.Range(0, 3);
        stepGenerator.audioSource.clip = stepGenerator.footStepSounds[randomIndex];

        stepGenerator.audioSource.Play();

        yield return new WaitForSeconds(timer);

    }
}

I don’t there is problem with the sounds, they are from the Standart Assets Pack if so, there is something up with the code and I can’t understand what.

Make sure you have ‘Loop’ unchecked on your audio source

Holy coroutines, Batman! :slight_smile:

The reason it’s constantly playing footstep sounds is… you are constantly telling it to. Look at your code:

if (isMoving) PlayFootSounds();

That’s called from Move, which is called every update. So PlayFootSounds() starts a new coroutine every frame, and each coroutine plays a sound, waits for ‘footsteptimer’ seconds, and then stops.

In case you weren’t aware: when you start a coroutine you (more or less) launch a new thread running the method you supply. You can start as many new threads as you like, all running the same method, which is what’s happening here.

My advice would be not to use a coroutine at all for this. Instead:

    float footstepTravel;
    public float footstepInterval;
    private void Move()
    {
        ...
        if (isGrounded)
        {
            footstepTravel += velocity.magnitude;
            if (footstepTravel > footstepInterval)
            {
                PlayStepSoundRightNowNoCoroutine();
                footstepTravel -= footstepInterval;
            }
        }
    }

Much simpler, and it will cope with different movement speeds.

1 Like