Calling "QueueFree" in a callable on the target node

Godot Version

v4.2.2.stable.mono.official

Question

Having issues calling QueueFree() on a instance of AudioStreamPlayer2D that is added as a child of the GetTree().Root.

Essentially the QueueFree seems never to be called as I periodically log out the children of the tree root and it keeps growing.

I know that the signal connection is generally fine, because if i connect it to some other say, static function that just logs, I will get a log in godot once the stream finishes.

Any ideas would be helpful, but I would like to is possible keep the general idea, I dont want to call QueueFree on this sound in the current script (which happens to be the thing making the sound), as I also want to queuefree this but allow the sound to finish if still playing.

See code below

      AudioStreamPlayer2D soundEffect= new() {
            Stream = soundEffectAudioStreamMP3,
        };

        GetTree().Root.AddChild(soundEffect);
        soundEffect.Connect("finished", new Callable(soundEffect, nameof(soundEffect.QueueFree)));
        soundEffect.Play();

I have also tried connecting to the signal before adding as a child, and also tried different approaches to the callable as below

soundEffect.Connect("finished", new Callable(soundEffect, nameof(QueueFree)));

Seems if i create a custom class like so

using Godot;

public partial class soundEffect: AudioStreamPlayer2D {
    public void QueueFreeOnFinish() {
        QueueFree();
    }
}

and call it like this

SoundEffect soundEffect= new() {
            Stream = soundEffectAudioStreamMP3,
        };

        soundEffect.Connect("finished", new Callable(soundEffect, nameof(soundEffect.QueueFreeOnFinish)));
        GetTree().Root.AddChild(soundEffect);
        soundEffect.Play();

Then it will QueueFree, does AudioStreamPlayer2D not implement a QueueFree function by default? I assume it should as it implements Node

You can try using C# events to hook up the signal instead of instantiating a new callable by referring to a method’s name.

AudioStreamPlayer2D soundEffect = new() {
    Stream = soundEffectAudioStreamMP3,
};

GetTree().Root.AddChild(soundEffect);
soundEffect.Finished += soundEffect.QueueFree;
soundEffect.Play();
3 Likes

This also works, which is cleaner than creating some extra class for sure, but i am surprised using connect does not work. For this case at least I will use your suggestion, much cleaner and more straightforward. Thanks!