The Godot Community Forums are back up and running! Please read the the announcement post for important information on what happened. Thanks!

[SOLVED] playing a random sound after the previous one stops?

lucas2606lucas2606 Posts: 2Member
edited January 30 in Audio

hi :) i'm new to Godot. this is my first day with the engine and my coding skills are very poor. i'm trying to play a random sound when the previous one stops, but i can't make it. i got a "control" node and 4 audiostreamplayer nodes as childs, "s1", "s2", "s3" and "s4". my control node code is this:

extends Control

var a =
var sound = 0

func _ready():
var sound = a.randi_range(1,4)

func _process(delta):
if get_node("s"+str(sound)).is_active == false:

the first part of the code works... it randomly plays one of the 4 sounds at the beginning of the scene. i don't now if this is the best way to do it, but it's the way that i found :P
the problem is that i can't make that when that first sound stop, another one start. the conditional "if get_node("s"+str(sound)).is_active == false:" give me the error "invalid get index 'is_active' (on base: null instance)"
probably is a very noob mistake...

Best Answer


  • s9menines9menine Posts: 3Member
    edited January 26

    First off - you probably don't want to put that in the _process function. You might want to define your own functions instead.

    Also, a slightly cleaner and less error-prone way of choosing a random one out of a fixed number of choices would be to put them in an array, shuffle() it, and access the first entry.

    onready var players: Array = [$s1, $s2, $s3, $s4] # We use the onready keyword because we're dealing with referencing pre-existing nodes, I think
    func _ready():
    func _random_player() -> AudioStreamPlayer:
        return players[0]

    To play from these four sounds non-stop, you could use a while loop.

    func play_sounds(): 
        var i := 1
        while i == 1:
            var player := _random_player()
            # yield waits for the specified object (player) to emit the specified signal ("finished") before moving on
            yield(player, "finished") 

    Call play_sounds() in _ready() for immediate autoplay when the parent node gets loaded. Also you didn't need to use a Control node for audio, that's usually used for GUI stuff, a regular plain Node would suffice.

  • cyberealitycybereality Posts: 928Moderator

    Nice solution. Quick question, though. Why use i == 1? Can't we do this?

    while true:
        # some stuff
  • s9menines9menine Posts: 3Member

    @cybereality It works! I just didn't know you could use the word true on its own like that haha, thanks for the tip!
    Another reason to use an i might be to change it later and break the loop, though in that case I should've declared it outside of the function.

  • cyberealitycybereality Posts: 928Moderator

    To break out of a loop, you just call break.

    while true:
        # do stuff
        if stuff_is_done:


  • cyberealitycybereality Posts: 928Moderator

    Ah, just noticed you're a new member. Well, welcome to the forum! =)

  • s9menines9menine Posts: 3Member

    Thank you! :3

  • lucas2606lucas2606 Posts: 2Member
    Accepted Answer

    hey! thanks for your replies! the mail with the notification went directly to the spam folder...
    I received two solutions in the Q&A section. I used the yield option
    here's the link:

  • TwistedTwiglegTwistedTwigleg Posts: 3,120Admin

    @lucas2606 said:
    hey! thanks for your replies! the mail with the notification went directly to the spam folder...
    I received two solutions in the Q&A section. I used the yield option
    here's the link:

    Great! Thanks for linking to the solution.
    Also, I changed this discussion to a question and marked your post as the answer.

Leave a Comment

BoldItalicStrikethroughOrdered listUnordered list
Align leftAlign centerAlign rightToggle HTML viewToggle full pageToggle lights
Drop image/file