How to play sound effect once?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By CreekWorks

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)
:bust_in_silhouette: Reply From: jgodfrey

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.

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!

CreekWorks | 2020-05-12 02:16

:bust_in_silhouette: Reply From: napo2k

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 :smiley:

:bust_in_silhouette: Reply From: MindaugasLabr

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 ;).

Thank you for this answer. I had the loop option unchecked on the Inspector but I didn’t re-import the sound :slight_smile:

gerep | 2023-01-08 14:27

This is the real answer.

animanoir | 2023-03-03 00:58