0
\$\begingroup\$

I have a sound effect in my game that I want to play every time there is a collision detected, the problem is that the collisions are very frequent and the sound plays many times and gets overlapped, which doesn't sound good.

The code is simple enough, I just put a walkSound.Play() in the OnCollisionEnter method.

I also tried using a coroutine but I don't get the desired result:

private void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.tag == "Ground")
        {
            StartCoroutine(WalkSound());
        }

    }

IEnumerator WalkSound()
    {
        walkSound.Play();
        yield return new WaitForSeconds(0.41f);
    }

The WaitForSeconds could be above the playing code, but then there is an unnecessary delay that I don't need.

Basically what I want to achieve is, to have code execute the Play() method only when the previous iteration of the sound reaches 0.41f seconds. This is similar to having an if statement that checks if the sound is already playing, but I want the sound to overlap at a given time.

Hope I was clear enough, any help appreciated. :)

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Side note: use collision.gameObject.CompareTag(“Ground”) for better performance \$\endgroup\$ – Ed Marty Jul 1 '20 at 13:28
  • \$\begingroup\$ Thanks for the tip! \$\endgroup\$ – Jiehfeng Jul 2 '20 at 8:24
1
\$\begingroup\$

One way to do it is to keep track of a state variable, like so:

private bool soundReady;    
private void OnCollisionEnter(Collision collision)
    {
        if (soundReady && collision.gameObject.tag == "Ground")
        {
            soundReady = false;
            StartCoroutine(WalkSound());
        }

    }

IEnumerator WalkSound()
    {
        walkSound.Play();
        yield return new WaitForSeconds(0.41f);
        soundReady = true;
    }
\$\endgroup\$
1
  • \$\begingroup\$ Thank you! Works like a charm. \$\endgroup\$ – Jiehfeng Jun 30 '20 at 9:12
0
\$\begingroup\$

When you want to avoid playing the sound while it is already playing, you can check the property AudioSource.isPlaying and only play the sound when it isn't already playing.

But with walk sounds, you likely want the sound to loop while a certain condition is fulfilled and stop it when that condition is no longer fulfilled. You can do that by checking the "Loop" box in the AudioSource component and then use OnCollisionEnter and OnCollisionLeave to switch it on and off using Play() and Stop().

\$\endgroup\$
1
  • \$\begingroup\$ Thank you for your answer, I thought of doing that, but I wanted it to be more dynamic and realistic where as the collision happens there is audio feedback. \$\endgroup\$ – Jiehfeng Jun 30 '20 at 9:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.