Playing Sound before queue_free()?

Godot Version

4.3

Question

Ok, I’ll admit it in the ensuing months since I last used Godot I have forgotten how to play a sound on a object that is going to be destroyed - ie queue_free(). But, I really thought this would work:

I had this:

Autoload.sound_manager($tank_explode);
queue.free()

where Autoload is a global var in a script by itself, with this function:

func sound_manager(sound: AudioStreamPlayer2D):
print(“play sound Godot”);
sound.play();
#end

but, the queue_free() duly kills off the sound. Works fine if I commented out the queue_free but I really expected it to work. In the end I had to resort to:

tank_explode.play() # Start the sound
await tank_explode.finished # Wait until it’s done

So why didn’t that work?

Regards.

Your $tank_explode node is being destroyed along with your parent node.
You’d need to reparent() this $tank_explode node to the autoload node, or root, or anything else that is not being destroyed, play the sound, and then queue_free() that node too.

3 Likes

Aha, now that you’ve explained it it makes perfect sense.

I was following some advice that I found on that Google AI - but, they sort of left out that step.

Now, after some testing using the await signal is causing the game to NOT work correctly. Why, don’t know! Which is why I have been trying to get the soundfile to play another way I thought the autoload.gd file would be the way to go:

#To play a sound without using the "await" signal
var sound_to_play = preload("res://art/soundFX/Tank explosion.wav");
@onready var audio_player: AudioStreamPlayer2D; 

func sound_manager():
	print("play sound Godot");
	audio_player.stream = sound_to_play;
	audio_player.play();
	#end

But the error is:

Invalid assignment of property or key 'stream' with value of type 'AudioStreamWAV' on a base object of type 'Nil'.

Now I think I understand why it’s because there is no child node added, but the thing is it’s just a script so I can’t add a child node. Is there anything I can do here?

Your autoload can be a .tscn scene too, doesn’t have to be .gd script

Wh, wh, wh, what? it can?!?

Well, I never knew that you could use a TSCN file as a global!

And after trying it out, It can, it does, and more importantly it works :smiling_face_with_sunglasses: :smiling_face_with_sunglasses: :smiling_face_with_sunglasses: Thanks again.

Another solution is:

# This is just good practice when coding in GDScript
@onready var tank_explode: AudioStreamPlayer2D = $tank_explode

tank_explode.play()
await tank_explode.finished()
queue.free()

This will solve the other problem you may have created for yourself is that an AudioStreamPlayer2D plays the volume based on the player’s distance to the object, and depending on how you pass it around, it can sound closer or farther away than intended because you can reset the coordinates for the node. It may even seem like it’s not playing at all because it is too far away for the player to hear. Which will drive you nuts while you try to debug it. These are all things the AI should have warned you about.