It documents the process of me smashing my head against the keyboard to build a game called LETSGO
It’s gotten long enough to break into several sections:
So now we have compiling accessors for a Quartz Clock, we can use it in blueprints.
Resources for this:
Start the Clock
I have a BP_ClockMain
blueprint to act as a shared clock for instruments.
- On the beginning of play we
Create New Clock
- This requires loading the Quartz subsystem
- We pull off from In Settings to setup time signature.
Next we use the Pointers Are Hard accessors we built to store this main clock in game state. We also set the beats per minute and start the clock.
174 BPM is fast. It happens to be the standard BPM for drum and bass music.
Drum Blueprint
With our MainClock
created and started, we can now play things in time.
The first thing to play: the Drums!
Specifically a kick drum. Our (western cultured) ears are trained to tie the kick drum to the rhythm of a piece of music. It’s also just a single stem to export from Ableton. Easy as pie.
To prove the system I’ve designed here is working end-to-end, I want just a super simple four-on-the-floor drumming pattern to play when the game starts.
So I create BP_Instrument_Drum
blueprint. The naming convention here indicates this is a blueprint, grouping instruments together, specifically the drum.
Should this be named a kick drum? Will the snare be separate?
I’ll take a page from the lazy writing of Star Wars: The Force Awakens: “A good question for another time.”
I digress. The main point here is that I am getting the game mode, casting to my custom LetsGoGameMode
, which has an accessor to my custom game state’s MainClock
. We set that to a local variable in the Drum blueprint.
Now that we have a Quartz clock- nay, the main quartz clock, we subscribe to the timing the drum cares about.
In this case, a custom QueueMusic
event will fire every quarter note.
Queueing Quartz Sounds
The fact we’re queuing the music is actually really important.
I had forgotten this step, and instead of queuing the music I Play Quantized
directly. It sounded clipped, offbeat, totally wrong.
I was stumped on why this was before going back and realizing I hadn’t queued the sound to be played.
By Queueing, we are offloading the work from the main gameplay threads to the quartz managed audio threads.
CPU audio buffer latency requires some “magic” to have sounds at beat-perfect timings.
The Quartz audio subsystem in Unreal is that magic.
Through queueing, we are telling Unreal to do the “Play Sound” work in the dedicated Quartz audio threads.
In the image above you see it’s just a simple Spawn Sound 2D that we then play quantized.
A 2D sound has no location in world space, its just played- useful for things like UI menu sounds or whatever.
For our purposes its good enough though.
Eventually I might like to have it in world space- build literal surround sound based on player location- but that is down the road.
With that the kick drum plays, on the beat, as expected.
And here’s what it looks like:
A bit of hitching at the beginning, as the sound starts playing right on begin play.
Could fade this in on trigger, that would be a good metasound task.
Also would be good to sync the platform hit to line up with the bar.
That would be interesting because it leads to a whole bag of potato chips: Syncing gameplay actions with the beat.
As demonstrated you are not forced to hit the platform.
Another Idea:
Area Sound Blueprint
- Blueprint location as source of instrument sound.
- Dynamically scaling invisible sphere.
- Sphere controls volume of an instrument?
- Niagara particle system also tied to sphere
- Ambient light zone thingy also tied to the sphere. Forget what thats called….
Instead, I worked on the following: