Coming from the Halo:CE engine originally where music management was quite simple (just controlled via commands in a script), I wanted to create something similar using blueprints and easy macros.
Trying to play songs simply in a sequence using the regular audio mixer did not bode well, as small delays started popping up during the transitions. Additionally, that audio mixer did not easily allow the user to access and play different sounds on command. So the simplest solution was to create a new blueprint class for music tracks.
- Easy to use commands to call a child of the base music blueprint and start playing it
- Correctly play tracks without delays
- Use of intros, transitional intros, loops, alternate loops, transitional outro, and outro.
- Functions to start playing alternate loop, stop music, and stop music using a fade out with timed duration.
- Macro library that allowed the commands to be called anywhere (more on this later).
Lets look at some code:
This is the main event graph in the BP_BaseMusic class.
Some notes. I'm using Rama's Victory plugin to allow me to fade out my custom music sound class. This made it really simply for the fade out function, which is really the only reason its used. If you don't want a fade out function then you don't need to include it, but I found this to be the quickest / easiest way to implement a fade function without using an audio component and just simple Play Sound 2D nodes. This method also assumes all you cues are assigned to that sound class. The only limitation this has is that when you fade out this track you fade out ALL music, but in my case thats not a big deal.
The timeline for the fadeout is over one second long. We use the set play rate function and a input to control the speed of the fade out.
Otherwise, the code is quite straightforward. We get the audio cue's duration and delay by that and simply play the next cue (or loop). We also check if the transitional cues are valid, considering these are not always necessary, but more so there to help if needed for the composer.
We also had three functions: StopMusic, PlayMusic, and PlayAltLoop.
- StopMusic simply checks to see if the loop has even fired yet (in case it was called to early), and if it has, it then clears the loop music function and sets the "MusicFinished" boolean to true.
- PlayMusic simply calls the custom event BeginPlayMusic.
- PlayAltLoop simply sets the "PlayAltLoop" boolean variable to true or false based on a bool input when called. This is so it can be called again to be set to false.
I then created a simple macro library that has simple functions and inputs that can be called from any actor or level blueprint (theres another macro library specifically to be called from UMG if needed).
Start music - only input it requires is the child blueprint CLASS that contains all the sound cues we want to play. It returns the created instance.
Stop Music and Play Alternate - simply just get the instance and call the respective functions. Honestly these aren't necessary since you have to get the instance anyway but added for consistency.
Fade out macro - we get an input for the play rate and then find all currently playing music actors and fade them out.
From here, we can just easily call the start music macro, plug in a child of the base music class and let it play!
Lastly, I've been working with Andrzej Ojczenasz for the music of Epitasis. He's been creating some really great stuff, and I can't wait to share it with you all quite soon.