DEADBEAT Devlog #00: BPM Events


Project Type: Prototype
Engine: Unreal Engine 4.24.2
Language: C++

In this Devlog we'll go over some of the hurdles we encountered as well as the process of implementing BPM (Beats Per Minute) events into a small Unreal Engine Prototype.

This prototype is served mainly as exploration for the DEADBEAT development. Code and methods that are used in this prototype are mainly focused towards development speed rather than performance or implementation.

Analyzing BPM to Seconds

The first important thing of this prototype was figuring out the way we would be getting a time from the BPM. This allows a representative value of the time between each Beat in seconds, which we knew we needed.

We stumbled across this picture that had all the simple formulas summed up.


Source: https://music.stackexchange.com/questions/24140/how-can-i-find-the-length-in-seconds-of-a-quarter-note-crotchet-if-i-have-a-te
By Bob Broadley.

This formula is quite simple: There are 60 seconds in a minute. Dividing this by the BPM will give you the result in seconds. Example: 80BPM song --> 60/80 = 0.75 seconds between each beat.

Applying a Timer that calls a function every beat.

Knowing the seconds between each beat, initiating a timer to call a function every set number of seconds is not too hard.

We made a new C++ class derived from a Character (but this could honestly also be an actor) called BPMTicker which would serve as a music handler and BPM event caller in this prototype. Here we made a function that I wanted to be executed every Beat, and as rate we set the number of seconds between each beat.

Considering we’d want to keep track of when it’s the first beat of a bar, I keep an integer that counts to 3 and resets to 0 based on the Beat function calls. 0 would be the start of a bar.

Implementing Music and SoundFX

Communicating through C++ with sounds looked a bit daunting at first but we quickly found some nice articles online that guided us towards the good way.

We start of by importing some background tracks for testing, and a sound to track the BPM ticks/Calls.


We used these sounds in a Sound Cue since this is enables us to switch easily between music as well as doing some simple sound modulation.

One of the most common problems we encountered is not knowing the includes or knowing when we need an include. We highly recommend to constantly keep the Unreal Documentation open to search any C++ functions u need. It shows you what include you need. https://docs.unrealengine.com/en-US/index.html

Using ConstructorHelpers we can find these Sound Cues, use them to create SubObject AudioComponents and attach these to the RootComponent of our BPMTicker. This serves well enough for this prototype. Using the AudioComponent we are now fully in control to play/pause/stop whatever is in these audio cues.

Desynced Timer & Music

Problem: When starting the project, music starts playing, timer starts ticking, but they’re desynced?

There are multiple causes for this problem we discovered throughout experimentation:

  • When starting there’s a small delay, it’s better to have the game already started up, then use Input to initiate the music and timer. This ensures them to start simultaneously without desync.
  • Make sure the Song is BPM steady and Starts at 0 seconds. This was easily modified by opening FL studio and cutting the 1 second silence I encountered in one of the songs I used.

First Results

Now we finally had some first results by making the beat function spawn random cubes in a certain range on a random location.
GetWorld()->SpawnActor() was the most convenient for this specific task at this time.

https://streamable.com/ier9n

Adding Animation Timing

Considering the traps in DEADBEAT must move on the beat or active/deactivate on the beat, we figured trying this out in this prototype would be a convenient choice.

We simply spawn a trap actor that I created as a separate class.

This trap class only has a USkeletalMeshComponent which allows us to load in a mesh and animation through a Blueprint child of this class. It also has a Deactivate and Activate function that will handle playing the animation either forwards or backwards.

It was a huge challenge figuring out how to Play animations through C++ code. We tried multiple things;

  • Creating an Animation Montage
  • Creating an Animation Blueprint

In the end the most convenient and easiest implementation for this prototype was loading it all in through the SkeletalMeshComponent. Calling Play would allow the Mesh to play the animation.

SetPlayRate was used to either play the animation forward or in reverse, corresponding to activation and deactivation.

We could now call these deactivate and activate functions based from the BPMTicker class corresponding to the Tick value. Which gave us the following result:

https://streamable.com/4wbql

Parameterizing to do quick changes

Making the BPM a parameter, and using sound Cue’s, We can easily swap out the music and set the BPM. As proof of concept here’s another video with the same result as before, but with a different background track.

https://streamable.com/zw1mi

Increasing music speed and BPM whilst remaining synced.

The first problem we encountered with trying to speed up the music is that Unreal Engine does not have a build-in speed-up method or anything similar for sound. However, increasing the Pitch also increases the speed of the audio, which is close to the result we want in DEADBEAT.

The second problem was syncing the BPM to the music. For this we had reset the timer and give it a different call time, as well as calculate this call time.

Calculating the call time was not too hard. We keep the time the song is playing, and use FInterpTo to interpolate between 1.f (no speed up) to 2.f (double speed) using this time and a interpolation speed value. We then proceeded to use this value as the “PitchMultiplier” for the background audio component.

We then reset the timer by simply setting a timer with the same handle, dividing the previously acquired call time by the interpolated value to speed up the calls between each beat and using the result as call time for the new timer.

This resulted in a nice ending result for this prototype (for now).

Next week we’ll be experimenting with new prototypes so be sure to check out the upcoming Devlogs if you’re interested in the early stages of the DEADBEAT development:

  • Grid based spawning
  • Dead Player Experience
  • Multiple Inputs
  • Pick-up/abilities

This is a very steep learning experience for both Developers of DEADBEAT since both of us have very low experience in UE4 C++, but through these prototypes we are learning the ins and out of it.

DEADBEAT

Get DEADBEAT

Leave a comment

Log in with itch.io to leave a comment.