+2 votes

Hi.

I'm new to Godot and I'm trying to play an explosion sound effect when deleting an object.
Basically when bullet is in collision with object, play sound effect and delete object.

The problem is that the AudioStreamPlayer is a child of the object I want to delete and because I delete the object on collision, the sound never play. I was thinking about to put the AudioStreamPlayer higher in the hierarchy and then send a signal to play it, but the problem with that is I have many instances of this object in the scene and I may delete multiple in short amount of time and so I need to play multiple instances of the sound but Godot seem to stop and start over the same sound when call the .Play() method of AudioStreamPlayer.

So I have two solutions in mind but I dislike both.

  1. Send a signal to the root node higher in hierarchy when object is about to exit, create an instance of the AudioStreamPlayer higher in hierarchy, play it, when finished, delete AudioStreamPlayer instance.
  2. instead of deleting the object on collision I play the sound and delete the object after the sound is finished.

The reason I don't like the first option because it is creating a mess in the project and also don't like the idea to constantly create and delete instances of sound object. And the reason I don't like the second option is that I still need to get rid of the object as soon the object colliding with the bullet so then what I would also need to do is play the sound, hide the object, disable collision mask so the player and everything stop interacting with it and then delete it when the sound finished.

Is there any better way to play multiple instances of a sound without need to go trough so much trouble or to play a sound when we delete an object?

In most game engines there is normally two audio objects to use one for Music and one for Sound. The difference is that a Music object can play only 1 instance of audio at the time and the Sound object can play multiple instances out of the box, no work around required. I can't find anything like this implemented in Godot but AudioStreamPlayer which seems to allow to play only 1 instance of the audio at the time. I need to create instances of the AudioStreamPlayer in order to solve this.

I would appreciate any help.

Thanks.

in Engine by (68 points)

2 Answers

+2 votes
Best answer

Similarly to this question: https://godotengine.org/qa/40610/particle-trail-projectile-leave-behind-removing-projectile
An answer to your initial problem is simply to not destroy the node immediately. Similar situations involve playing an animation for that explosion or letting particles fade out.
Another idea is to put the explosion sound in an explosion scene which you instance, rather than playing the sound from a node child of the thing you are destroying.

About the side-note about polyphony, that's another concern I share (which isn't necessarily a problem here though), for which I opened an issue: https://github.com/godotengine/godot/issues/23541

by (28,789 points)
selected by

Thanks a lot. I haven't thought about putting the explosion sound in to it own scene and then create an instance of the explosion scene that take care of playing the sound and delete itself when finished. It is just perfect, exactly what I need. Clean and simple solution :)

I also thought about making the object only invisible and disable collision mask and wait for the sound to finish, but I did not like that either. In most engines you can just play a sound and don't worry about any of this because the sound remain in memory as long it playing and then the garbage collector take care of it when it done. I was hoping there is something like that in Godot. But I like the idea of the explosion scene because it is self containing I only need to instantiate it on destroy and it will take care of it self. it almost that simple and clean :)

0 votes

I used this for one of my games, it technically reparents the sound itself to the parent of the its parent (the bullet, in this case):

func _ready():
    connect('finished', self, 'queue_free') # or you can connect this in the Inspector and delete this line
    get_parent().connect('tree_exiting', self, '_reparent')

func _reparent():
    var new_parent = get_parent().get_parent()
    get_parent().remove_child(self)
    new_parent().add_child(self)
by (4,163 points)

Thank you but it seems not much different than creating an instance of AudioStreamPlayer manually when the object is exiting.
But thanks anyway, at least I know I can also re-parent nodes. I didn't know that :)

So there is no "easy" way where an instance of the sound would be played by default and deleted once finished. We need to take care of this manually in Godot?

I was hoping there is a method or node hidden somewhere to help with this.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.