Cutting sound effects


By: Henrique Campos

When dealing with sound effects, it is a common problem to have the audio cut when picking collectibles like coins, hearts, or when killing enemies.

Sound effects stop because we often free the node that’s playing the sound indirectly. For instance, when the player touches a coin, we call queue_free() on the Coin node. The Coin contains an AudioStreamPlayer that gets removed from the game before it finishes playing the “picked” sound effect.

Screenshot of a Godot demo with five aligned coins

To solve that, we can use an AnimationPlayer. Godot’s animation system allows us to sequence audio, animations, and to call functions using as many animation tracks as we want.

The Picked animation

In the picture above, you can see we’re calling queue_free() only at the end of the animation after the sound finished playing.

With this approach, we can also disable collision shapes and avoid triggering a queue_free() or any unexpected behavior, like a character dying twice or picking a coin or a power-up more than once.

Using animation, we can also see the duration of a sound effect using an Audio Playback Track, which allows us to use a Call Method Track to call the queue_free method when the sound effect finishes playing.

Picking up a coin

For example, let’s make a coin that we pick when clicking on it. Once picked, the coin performs an animation, plays a sound, and fades on the screen. Then we call its queue_free() method.

Here is the Coin scene setup:

Coin scene hierarchy

We have the following signals from the Area2D connected to the Coin node:

Area2D signals connections

For the Coin script, it reacts to the Area2D signals. It gets brighter when the mouse enters the Area2D. It turns back to its default Modulation when the mouse exits, and it plays the Picked animation if we left-click inside the Area2D.

extends Node2D
class_name Coin

onready var animation_player := $AnimationPlayer
onready var sprite := $Sprite

func _on_Area2D_mouse_entered() -> void:
	sprite.modulate = Color(1.2, 1.2, 1.2)

func _on_Area2D_mouse_exited() -> void:
	sprite.modulate = Color.white

func _on_Area2D_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void:
	if event.is_action_released("left_click"):"Picked")

The critical part is the Picked animation. Let’s break it down:

The Picked animation

First, we add an Audio Playback Track that uses the AudioStreamPlayer to play the Coin.ogg sound. Then we disable the Area2D > Monitoring and Monitorable properties to prevent it from detecting any mouse events. In parallel, we animate the Sprite > Position and Modulation to give players visual feedback. Doing so shows that the coin got picked.

Then we have a Call Method Track with a keyframe on the very end of the animation calling the queue_free method on the Coin object, ensuring it gets removed from the SceneTree after the sound effect and visual animation finish.

Become a better game developer

Join our weekly newsletter and get our latest game creation tutorials, tips, and open-source tools right in your inbox.

🔒 No spam. Unsubscribe anytime.

Made by

Our tutorials are the result of careful teamwork to ensure we produce high quality content. The following team members worked on this one:

Henrique Campos


Nathan Lovato