+2 votes

I am trying to get a sound effect to play once when my object is at a certain position, I'm using a AudioStreamPlayer2D for my audio. The audio is Not assigned to loop.
Thank You!

Here is my code

extends KinematicBody2D


var move = Vector2()

func _physics_process(delta):
    if position.y > 328:
        move.y = -50
    else:
        move.y = 0
        $Audio.play()
    move = move_and_slide(move)
in Engine by (126 points)

3 Answers

+2 votes
Best answer

Generally, you'd use a boolean variable to accomplish that. However, you say you want to play it once, but I assume you really want to play it more than once in the entire game...

To really play it once you can do something like:

extends KinematicBody2D

var move = Vector2()
var sound_has_played = false

func _physics_process(delta):
    if position.y > 328:
        move.y = -50
    else:
        move.y = 0
        if !sound_has_played:
            sound_has_played = true
            $Audio.play()
    move = move_and_slide(move)

This just plays the sound if it hasn't been played yet. Then, once the sound is played, it sets a boolean so it won't play again. If you do want to play it again later, you'll need to set the sound_has_played back to false as appropriate to allow the sound to play again.

by (14,828 points)
selected by

Thank You! I wanted to play it once and only once because it is on the title screen and is for text that pops up once. Thank you again!

0 votes

There is something I wonder: when you say only once, is it only the first time any object is in the specified position? Only the first time a specific object enters that position? Once per game boot?

In any case, I think this is something that would be better controlled via Area2D and the body_entered signal.

You place an Area2D in the desired position and connect its body_entered signal to a function (it'll be, by default func _on_<FOO>_body_entered(body), where FOO is the name of the child Area2D), and you can then do something like this

func _on_FOO_body_entered(body):
    # Feel free to make any checks here, if you want a SPECIFIC object to trigger the sound, something like 
    # if body.get_class() == yaddayadda
        $Audio.play()

You can add the same boolean handling already suggested if you really want it to be played once, but this way, you don't need to update the values of position if the position changes. Moving the Area2D will do that for you. I think it's a less error-prone solution, and a good way to practice signaling in Godot, which is awesome :D

by (14 points)
+3 votes

Hoi, you can just press on your ogg file (int godot), than press import, remove loop and press reimport. Than drag the sound to AudioStreamPlayer and add function $AudioStreamPlayer.play() to your script. It will play once and you can reapeat it by adding another $AudioStreamPlayer.play() function ;).

by (28 points)
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 Frequently asked questions and 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 [email protected] with your username.