Welcome back to the Blightmare Dev Blog! Today we will be taking a quick look at the secret sauce that really brings a game to life – Sound. It’s easy to forget about sound when thinking about a mechanic or feature, but once you play through once with sound there’s no going back. In this post I’m going to discuss the way sound is implemented in Blightmare from the programming perspective. Hopefully in a future post I’ll be able to convince one of our audio designers to discuss what it takes to actually create the assets that I’ll be discussing today. Let’s jump right in.
There are two broad categories of audio in a game: Music and Sound Effects. We will start with sound effects because they are a bit more complex and then we will move on to music and finish with both together. Just a note: some of the videos in this post are not from the old version of the game because I unfortunately didn’t make a good historical record of audio integration.
To start off, lets look at a little sample piece of terrain without any music or sound effects
Blissa is running around without making a sound and that’s no good! Let’s add some footsteps in to give her a bit of life and feedback to the player as well. In order to do that we need to know when her foot hits the ground in the run animation, otherwise the audio may end up being more confusing than helpful.
There’s a couple of options here. We could slow down the animation in the editor and look at what the timing is and then put that into our code directly. This is pretty straightforward and doesn’t require anyone else, but it’s a little brittle. Consider what happens if the animation changes even slightly. Our timing numbers will now be off and we will have to go back in and recompute them. Not only is this a tedious process, but more importantly it’s hard to know when we need to do it. Programmers aren’t updating the animations themselves and we don’t want to be blockers in the art process so there’s a high chance that if we do the walk cycle audio this way, we will end up with some recurring bugs.
What we want is to give the artists a way to tell the code when Blissa’s foot is stepping on the ground so that we can then react to that in some way. It would be even better if we didn’t need to know which animation this was coming from because that’s another thing that might change as the art is iterated on. In fact, the less we need to know, the better. In programming, shared knowledge between systems is referred to as “coupling” and generally reducing it will allow for more reuse or flexibility between systems that work together. Blightmare uses a very common pattern called “events” to solve this problem for audio. An event is just a little message that some system creates and sends out to anyone that might be listening. The key thing here is that the creator of the message doesn’t care – or even know – if anyone is reading the message which means that coupling is reduced down to just the message contents and the message relay system.
In this picture you can see how the audio system is only interested in the fact that a footstep has happened – it doesn’t care how it happened – and when the step event is delivered, we will play the correct sound effect. This opens up the very helpful ability for us to simulate a footstep event for testing purposes without having to have a whole player character. Similarly, the player just tells the whole world that a footstep has happened. If we don’t have audio turned on, or it’s not ready yet, that’s totally fine – and nothing changes in the player code. This is perfect because now the player can be worked on independently from the audio without either of them breaking the other. Decoupling in action!
Alright. Enough talking, here’s Blissa with just her walking sound effects.
Excellent. Blissa already feels so much more alive than before! Now that we have a taste of the sound effects, the missing parts – jumping and landing for example – are really glaring. At this point, as a programmer, I again want to remove myself from the creative process as much as possible so that everyone can work independently and in parallel. This typically means the creation of some kind of tool that allows someone else to interact with the system without having to code. Sometimes this is referred to as “data driven” programming. For Blightmare, the sound effect hookup is exceptionally primitive, but it was enough to get many of the effects in for our demos. Doing proper audio integration tooling is still on my todo list unfortunately, so when I get to it I’ll be sure to do an update here. The way things work right now is this: There’s a list of events that the game can generate when various interesting things happen. To hookup a sound effect to an event, an audio designer just adds a mapping in our Audio component from the game event to the desired sound effect. It’s not exactly this simple, but I’ll save the details for a future post when I’ve had the chance to do proper audio integration. Here’s a snippet of the tool in Unity (note that there’s 35 entries in total right now!).
After integrating jumping, landing, and the net swing we are starting to get to a place where Blissa really feels alive and responsive. Here’s the same level with those effects turned on:
Perfect. It’s hard to describe the feeling that sound effects add to the sense of control over the character, but I assure you that it’s definitely a requirement for any level of immersion.
Now that we have a handle on some sound effects, we will turn to music. Music is actually rather straightforward in Blightmare. Currently we only support a single music track that loops. This is exposed to the audio designers as a single setting to keep things as simple as possible. With the music plugged in, we finally have the full complement of audio. Here it is all put together:
It’s like a real game! This is what I thought the first time I played the game with audio. Sound really adds another dimension to things in a way that is irreplaceable.
The last couple things I’ll put in here are some bloopers from trying to synchronize the walk cycle. In the first one, the timing is just slightly off – less than a tenth of a second I believe – but you can clearly hear the beats. The second is the same test but with the timing fixed. In this case, it was the animation events that were wrong. Only the animation had to change to fix it though – because of the nice decoupling.
This brings us to the end of the Ancient History series. Thanks for reading along! Next time I will take a look at a topic that is extremely important to the platforming genre: jumping. I hope you will join me.