This is my first blog post. If you notice anything out of the ordinary (styling, structure, content, anything), let me know so I can fix it and learn for my next posts!
There are multiple ways to play and manage music tracks for your game but most are linked to your scene. In this tutorial we'll make an autoload music manager that will allow to you play background music independent from your game scenes.
You can use another version of Godot, but this tutorial is written with Godot 3.1.
Download Godot at godotengine.org
Since we're making a music player, you'll need two music tracks. Godot supports .wav and .ogg formats, but they recommend using .ogg for background music because it takes up a lot less disk space than .wav.
If you don't have music, you can find some nice free tracks at incompetech.
We're going to use the autoload feature in Godot. This lets us add static nodes to the scene tree that will always exist, independent of our game scenes.
This is perfect to keep our music playing, even if we change the scene.
If you want to learn more about autoload you can check out the Godot docs.
Our project will consist of 3 scenes: Scene1 and Scene2 will be our regular game scenes, and we'll add some buttons to them to manage the music.
MusicController will be our special autoload scene. We'll add some custom functions to this scene so that we can easily play our music from anywhere in our game.
Create a new scene and call it
Scene1. Then add 1 label and 3 buttons as in the screenshot below.
Add a script to the root node of the scene, and connect the
pressed() events of the three buttons to it.
# Scene1.gd extends Control func _on_GoToScene2Button_pressed(): get_tree().change_scene("res://Scene2.tscn") func _on_PlayTrack1Button_pressed(): pass # Replace with function body. func _on_StopMusicButton_pressed(): pass # Replace with function body.
Now make another scene and call it
Scene2. Add 1 label and 2 buttons.
Next, add a script to the root node of the scene and connect the
pressed() events of both buttons to it.
# Scene2.gd extends Control func _on_GoToScene1Button_pressed(): get_tree().change_scene("res://Scene1.tscn") func _on_PlayTrack2Button_pressed(): pass # Replace with function body.
Now it's time to create our music controller scene.
Create a new scene and call it
MusicController. Add 1 AudioStreamPlayer to play our music.
Add a script to the root node of the scene and add the following code to it:
# MusicController.gd extends Control # Load the music player node onready var _player = $AudioStreamPlayer # Calling this function will load the given track, and play it func play(track_url : String): pass # Calling this function will stop the music func stop(): pass
As you see, we have defined 2 functions:
stop(). We'll be using these to play and stop the music as needed from our game scenes.
Side note: wondering what that
track_url : String syntax is? It's a new feature in Godot 3.1 called optional typing. It means we expect that function parameter to be a string, and the editor should warn us if we call that function with anything that isn't a string.
Let's begin with the easiest function to implement. The
stop() function simply needs to stop the music - hence its name.
Checking the documentation, we can see that AudioStreamPlayer has a
stop() method, so all we need to do is call that method.
func stop(): _player.stop()
This one is a little more involved. When the
play() function is called, we need to do 3 things:
- Stop the previous track
- Load the new track from the
- Start playing the new track.
Luckily, it's not difficult to do any of these things with GDScript.
To stop, the previous track, we simply call our own
Next, we need to load the new track. GDScript makes this very easy with the
var new_track = load(track_url)
Now we have to update the player and tell it to use the track we just loaded.
Returning to the documentation, we can see that AudioStreamPlayer has a property
stream that we can set.
_player.stream = new_track
Now all we have to do is start the track.
Our MusicController script looks like this now:
# MusicController.gd extends Control # Load the music player node onready var _player = $AudioStreamPlayer # Calling this function will load the given track, and play it func play(track_url : String): var track = load(track_url) _player.stream = track _player.play() # Calling this function will stop the music func stop(): _player.stop()
The last thing we need to do is tell Godot to actually load our autoload scene.
Go to the
Project menu and open
Project Settings. Then click on the
AutoLoad tab. This is where we can configure our autoload scripts.
An autoload script always has a path that points to the resource (either a script or a scene) that should be loaded, and a name that you can use to refer to it in your code.
Side note: You can also access autoload nodes through the scene tree. See the autoload documentation for more information.
To add our
MusicController scene to the autoload settings, select it in the Path field. You can look for it with a file browser by clicking the little button next to the field.
The Node name should automatically get filled based on the name of the scene. You can change this if you want, but we'll leave it for now.
Click the Add button to add the autoload scene to the project. It will appear in the list below.
Every autoload script has some buttons that allow you to edit or remove the autoload script, and to change the order in which they are loaded. They also have an enabled checkbox so you can temporarily disable an autoload script without having to delete it and re-add it if you want to test something.
Make sure enabled is checked for our new MusicController autoload script.
And that's it! Our autoload scene has been added and is now active in the project! This means we can access the
stop() functions we made through the global
MusicController variable. So let's try that out.
Scene2 scripts, we can now call the functions we need in the pressed events. The scripts will look something like this:
# Scene1.gd extends Control # Switch to the other scene func _on_GoToScene2Button_pressed(): get_tree().change_scene("res://Scene2.tscn") # Load and play track 1 func _on_PlayTrack1Button_pressed(): MusicController.play("res://tracks/track 1.ogg") # Stop the music func _on_StopMusicButton_pressed(): MusicController.stop()
# Scene2.gd extends Control # Switch to the other scene func _on_GoToScene1Button_pressed(): get_tree().change_scene("res://Scene1.tscn") # Load and play track 2 func _on_PlayTrack2Button_pressed(): MusicController.play("res://tracks/track 2.ogg")
Don't forget to set the correct paths to your tracks.
Now we can run the game and enjoy the music. Notice how it doesn't stop playing, even if you change to the other scene!
That's what autoload is all about.