Sound stops when object is destroyed

Hi there,

I'm currently trying to build a game that requires the character to pick up some items and I want a sound to play when an item is picked up.

below is the code that I have so far

var sound:AudioSource
var CollectSound:AudioClip

function Start(){
    sound = GetComponent(AudioSource);
}

function OnTriggerEnter(theOther:Collider) {

     if(theOther.gameObject.name == "MainChar") {

       audio.PlayOneShot(CollectSound);
       yield new WaitForSeconds(1);
       Destroy(gameObject);

   }
}

@script RequireComponent(AudioSource)

now the problem that I am facing is that the sound just stops because the item is destroy and I don't really want to yield it for a second.

Is there any way that I can attach the sound to an empty gameobject and make that play instead when my character collides with the item ? or is there any way else to code this ?

This sounds like an ideal situation to use AudioSource.PlayClipAtPoint.

This function does exactly what you want automatically - it creates a new audio source at the position specified, and cleans up the audio source afterwards, making it a "fire and forget" style function.

To use it in your script, you'd change the code to something like this:

var collectSound : AudioClip

function OnTriggerEnter(theOther : Collider) {

     if(theOther.gameObject.name == "MainChar") {

       AudioSource.PlayClipAtPoint(collectSound, transform.position);
       Destroy(gameObject);

   }
}

I am having the same issue, but my problem is the camera is far from the player and I tweak my AudioSource ramp for each sounds. But with this, I have no choice to use the default setting…

What I do is a bit different but works for me. I disable mesh renderer of the object and destroy in some seconds in order to let the audio effect to play till end.

gameObject.GetComponent<MeshRenderer>().enabled = false;
Destroy(gameObject, 5f);

I just had the same problem the other day and use this solution. I don’t know if it is efficient but it is similar to @oktemre solution: it is possible to edit the AudioSource in the editor and keep it as part of the prefab:

  • Create and empty GameObject child of the game object you want to destroy.

  • Add the AudioSource component to the empty GameObject. Edit the audio source.

  • In your script, create a reference to the AudioSource. I called it “effect”.

  • Then use this code to play the audio source:

    effect.transform.parent = null;
    effect.Play();
    Destroy(effect.gameObject, 1);
    Destroy(gameObject);

That way, the empty game object is detached from the destroyed parent and can play for 1 second and then get destroyed (or more time if you need).

The only drawback with PlayClipAtPoint, which is a really fine solution, is that you have 0 control over the audio source parameters, you might need to specify an audio mixer group for example.

You could implement your own PlayClipAtPoint which returns the AudioSource

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

If you want to see a more detailed explanation I’ve blogged about this.

When the player initiates the sound playing after collecting the item you will not run in trouble when the collider.gameObject - which has been collected - is gonna be destroyed.