Godot Version
v4.6.2.stable.official [71f334935] - Linux
Question
Hi,
Trying to play an OGG sound effect when the mouse left button is clicked but we hear nothing?
Not sure if this is an issue, but the sound effect is playing right before a scene change?
This is IDE editor plus GDScript source code.
Little lost, hope someone knows what we are doing wrong, thanks!
extends RichTextLabel
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
pass # Replace with function body.
func _input(event):
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
print("Left mouse button clicked at: ", event.position)
var sfx_player = AudioStreamPlayer.new()
add_child(sfx_player) # Must be in the scene tree to play
sfx_player.stream = load("res://resources/sound_effects/SND_MenuClick.ogg")
sfx_player.play()
# Optional: Automatically delete the player when the sound finishes
sfx_player.finished.connect(sfx_player.queue_free)
get_tree().change_scene_to_file("res://scn_godot.tscn")
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
pass
Yes, is issue with playing sound effect right before changing scene.
Not sure how to fix this issue above, any help would be appreciated.
what are the ogg’s import settings?
I don’t think I import the OGG.
The sound effect plays fine if I don’t switch scenes.
The better question to ask here is how to play audio between scenes?
I’ve done some Web searching, but would like to know the best method to implement…
you have to import it if you have it in the editor.
If it isnt in your game’s directory then it wont be imported, but if so, it definitely is.
Sorry, sound effect OGG IS in the game’s directory.
Any idea for having persistent audio(sound effects & music) between scenes?
Changing the scene will delete the current scene; you are adding an AudioStreamPlayer as a child of the current scene just before deleting it.
For this one-off audio stream player you are making in the script you can add it as a child of get_tree().root so that it is not part of the current scene. You can delete the node “sfx_player” found in your editor, it is not playing anything, and it is going to be deleted with the current scene.
Hi,
We have this solved.
Add below script as a Global and call the two functions to play music and sound effects.
(modify to your needs)
Both music and sound effects survive scene changing…
SS
extends Node2D
var MusicVolume
var EffectsVolume
var MusicPlayer
var MusicTotal = 1
var MusicCurrentlyPlaying = -1
var EffectPlayer = []
var EffectsTotal = 1
#----------------------------------------------------------------------------------------
func _ready():
MusicVolume = 0.5
EffectsVolume = 0.5
MusicPlayer = AudioStreamPlayer.new()
add_child(MusicPlayer)
for index in range(0, EffectsTotal):
EffectPlayer.append(AudioStreamPlayer.new())
if index == 0: EffectPlayer[index].stream = load("res://resources/sound_effects/SND_Menu_Click.ogg")
add_child(EffectPlayer[index])
EffectPlayer[index].volume_linear = EffectsVolume
EffectPlayer[index].stream.set_loop(false)
pass
#----------------------------------------------------------------------------------------
func SetMusicAndEffectsVolume(musicVolume, effectsVolume):
MusicPlayer.volume_linear = musicVolume
for index in range(0, EffectsTotal):
EffectPlayer[index].volume_linear = effectsVolume
pass
#----------------------------------------------------------------------------------------
func PlayMusic(index, loop):
if index < 0 || index > (MusicTotal-1): return
if MusicCurrentlyPlaying > -1:
MusicPlayer.stop()
MusicCurrentlyPlaying = index
if index == 0: MusicPlayer.stream = load("res://resources/music/BGM_Title.ogg")
MusicPlayer.volume_linear = MusicVolume
MusicPlayer.stream.set_loop(loop)
MusicPlayer.play(0.0)
pass
#----------------------------------------------------------------------------------------
func PlaySoundEffect(index, loop):
if index < 0 || index > (EffectsTotal-1): return
EffectPlayer[index].volume_linear = EffectsVolume
EffectPlayer[index].stream.set_loop(loop)
EffectPlayer[index].play(0.0)
pass
#----------------------------------------------------------------------------------------
func _process(_delta):
pass
Godot already has this function as linear_to_db, but you can set an AudioStreamPlayer’s volume linearly with .volume_linear anyways
So functions like this can be reduced
func SetMusicAndEffectsVolume(musicVolume, effectsVolume):
MusicPlayer.volume_linear = musicVolume
for index in range(0, EffectsTotal):
EffectPlayer[index].volume_linear = effectsVolume
But this may also be better as an AudioBus, so you can separate effects from music volume level and apply audio effects such as a Compressor to help if say your effects overlap and get too loud a Compressor can prevent that from being overwhelming.
Your volume also has this superfluous variable that is set to 0.5 and never set again. It will always play new sounds at half volume because of this.
Using index for music is very strange, you have one song defined for if index == 0, do you intend to make this an Array of music to choose from? It may still be better to allow passing a string filename in for any file to be loaded, rather than trying to remember which index is which song.
Similar index strangeness for effects. Only index 0 is set to a sound. Not sure why one would set it to loop, and if you did you’d have to stop it by Global.EffectPlayer[0].stop() rather than a method like they play functions.
If you change your global to a scene you can add a polyphonic audio stream to your Audio stream player, these will play multiple streams over each other making them great for one off sound effects while only instantiating a single AudioStreamPlayer.
I worry this code is LLM generated hence the strange styling unlike your other code, and strange errors/superfluous code.
1 Like