In Part 1 & Part 2 of our series we discussed how you might build and use a horizontal or vertical musical system in UDK. A horizontal system can be built relatively easily from the default nodes provided with Kismet. A vertical system becomes a bit more difficult stemming from the need to track bars and beats, keep multiple musical loops in sync, and create timed fades.
In order to have an intelligent music system that can keep multiple music files in sync you need to have a system that can account for the number of bars in a loop and the tempo/bpm of the music. For this purpose I have created a custom kismet node that uses a timer to loop a soundcue after a certain amount of time. This creates a seamless loop as the audio file plays back. The length of the loop is determined by the BPM, and the number of bars in the loop. These values are set as inputs to the Kismet node. This allows the values to be easily set in Kismet ahead of time, or on-the-fly while the game is running.
Instructions to use MusicBPM.uc as a Kismet node in UDK:
Unzip the MusicBPM folder into \Development\Src folder of your UDK install
The MusicBPM folder contains:
|_SeqAct_MusicBPM.uc (unrealscript file)
Open up DefaultEngine.ini inside the \UDKGame\Config directory with Notepad. (e.g C:\Projects\UDK-2011-08\UDKGame\Config\DefaultEngine.ini)
Search for EditPackages
Rebuild scripts from the UDKFrontEnd or just open the UDK Editor
If the editor asks if you want to rebuild scripts click YES
Using MusicBPM in a vertical music system
I developed the MusicBPM Kismet node as a way to create a music system in UDK that is aware of the tempo of the music and can react in a way that is more intuitive for a musician.
Multiple MusicBPM Kismet nodes are meant to work together to create a vertical music system that can play, loop, and mix music according to the action occurring in the game environment. All nodes will start playing at the beginning of the level using a Level Loaded Kismet node. If the audio is meant to heard at the beginning of the level we can feed the signal to the ‘Start’ input on the MusicBPM node to begin play at full volume. If the audio is not meant to be heard from the beginning then use the ‘Mute’ input. This will start playing the audio in sync with the other files, but the volume will be set to zero.
Any other Kismet node can be used to trigger MusicBPM. You just need to determine what game event you want to use to start the music system. It could be a location in the game world, health, time left in level, or any number of things. For the purposes of this example we will rely on the player’s location in the game world to trigger our vertical musical arrangement. In Kismet we can use a TriggerVolume to determine when a player has entered a certain area. This TriggerVolume will send a signal to the Fade input of the next MusicBPM node. The volume of the AudioComponent will increase from zero over a time set by Bars per Fade. To create a crossfade between two pieces of music set the output of the TriggerVolume to the Fade input of two different MusicBPM nodes. The node at full volume will start fading down to zero while the node at zero volume will fade up to full volume. This creates a smooth linear crossfade.
The MusicBPM node has a series of inputs that control how the soundcue is plays back:
Start – begins playback of the soundcue, volume at 100%
Stop – ends playback of the soundcue
Mute – begins playback of soundcue, volume at 0%. If already playing, toggles volume of soundcue between 0% and 100%,
Fade – increses or decreases the volume over a certain number of bars
The outputs give feedback to the audio system:
Out – this output fires when the node is first activated
Finished – this output fires when the soundcue has reached the end of the file
The node has input variables with information on the playback of the audio:
BPM – the tempo of the music loop
# of Bars – the number of bars in the music loop
Bars per Fade – number of bars used to fade the volume in/out
How it works
The MusicBPM is based off of a timer. It uses the values of ‘BPM’ and ‘# of Bars’ to determine the length of the audio loop in seconds. The result is then added to WorldInfo.RealTimeSeconds to determine when the music will loop. Every frame or tick in the game checks to see if this time has passed and if so it plays the audio file again. Along with checking the time the node checks the inputs at every tick to see if a signal has been received to stop, mute, or fade the audio. Once the signal has been received the node will either mute the AudioComponent or fade it in or out according to its current state. When the node receives a signal to stop it deactivates the node until it starts up again.