How to play a sound upon collision in Unity even when the object is destroyed

play sound after collision hit

Silence after an explosion or coin pickup is not exactly what we want, right?


Júlio Rodrigues ·

A really common situation in lots of different games to play a sound when something is hit, that is, a collision happened. Also really common is that this collision results in one of the two objects being destroyed.

I've been there too, we try several things but don't understand why the sound only clicks and pops or even worse, a total silence after the hit.

There are two very commons reasons for this to happen:

  1. The gameobject containing the AudioSource is destroyed.
  2. The collision method isn't called.

Each of these reasons has a different way to be diagnosed and fixed. Let's start with the first one that seems to be the most common.

The gameobject containing the AudioSource is destroyed

If you're sure that your collision code is being called, because you have proof, either via debug logging or because it has triggered any other thing in your game (particle instantiation perhaps?), then it's really likely that this is the reason.

The Unity editor might also log that "Can not play a disabled audio source".

You can solve this problem easily by using a method created just for this issue, the PlayClipAtPoint. This method is going to create an empty gameobject which the engine itself will be responsible for destroying after the sound finishes.

private void OnCollisionEnter(Collision other) {
    Destroy(gameObject);
    AudioSource.PlayClipAtPoint(hitSound, transform.position, 1f);
}

This solution has a gotcha, though. You can't redirect the output to a specific Audio Mixer Group using it nor change any of the regular AudioSource parameters. If you need to do that there are at least two solutions. The first alternative would be to create your own PlayClipAtPoint method in which you pass the Audio Mixer Group and return the AudioSource so you could change the other parameters:

public static AudioSource PlayClipAtPoint(AudioClip clip, Vector3 position, AudioMixerGroup mixerGroup){
    var go = new GameObject("PlayAndForget");
    go.transform.position = position;
    var audioSource = go.AddComponent<AudioSource>();
    audioSource.clip = clip;
    audioSource.outputAudioMixerGroup = mixerGroup;
    Destroy(go, clip.length);
    audioSource.Play();
    return audioSource;
}

The calling function could also change the outputAudioMixerGroup property, but it's such a common task that I think it's a good idea to have this as a parameter.

And the second alternative is to create this object right in the prefab, detach it from the parent before destroying it, and later destroy the detached gameobject. One advantage of doing it this way is that you can use the Unity Editor to tweak the audio parameters of the AudioSource instead of doing it by script.

Sounds complicated but it's rather easy to understand once exemplified.

prefab hierarchy
audio source setup
public void PlayDettaching() {
    var detachedGo = transform.Find("Audio").gameObject;
    var audioSource = detachedGo.GetComponent<AudioSource>();
    audioSource.Play();
    detachedGo.transform.parent = null;
    Destroy(detachedGo, audioSource.clip.length);
}

private void OnCollisionEnter(Collision other) {
    PlayDettaching();
    Destroy(gameObject);
}

If you use PlayDettaching on different types of components you could create an extension method instead of repeating this code. See the official unity tutorial on extension methods.

Collision Method isn't called

The diagnosis is generally made using logs. If you don't see anything in your logs after the collision happens it could be happening (not happening) because:

  1. There's no Rigidbody component on at least one of the game objects
  2. Even with a Rigidbody, there's no non-kinematic Rigidbody attached
  3. Colliders of one of the two objects are disabled or don't exist
  4. Method (OnCollisionEnter, OnTriggerEnter, ...) is named incorrectly, check the capitalization.

There are more reasons, but generally, the culprit is one of these four. Fix those and you should be able to hear your sound effect. Just be careful to fix what's described here and forget about what's explained in the beginning of the article, that is, the collision is detected but the AudioSource is destroyed right at the moment the sound starts to play.

If you're still not able to hear your sfx reach me on twitter or by email.

More fixes in your inbox

Solved your collision problem? Want to receive more tutorials like this in your inbox? Be sure to subscribe!

Detailed Unity Tutorials in your inbox

Subscribe if you want to receive articles and tutorials like this one right in your inbox. 

Classify in:
  • unity
  • audio
  • sound on collision
© Bladecast 2018. All rights reserved.