Working in Unity - 2D Ambiences

As much as I like working with middleware, sometimes it's just me and the game engine. To brush up on my implementation and C# skills, I thought I'd knock together a quick demo and implement some 'simple' audio. What became very obvious, very quickly, is that 'simple' concepts tended to end up being a lot more complex to implement than I originally thought!

Here you can see the level I'm working with. It is a demo scene from Quantum Theory's PolyWorld East asset pack. It's a beautiful level with enough audio opportunities for me to explore.

The systems I wanted to cover were:

  • 2D ambient sound attenuation
  • Random 'Container' for ambient one shots
  • Random footstep triggering on multiple surface types

Forest collision box

First things first: 2D ambience attenuation. The idea is that different locations of the level have a slightly different flavour of 'bed ambience', pretty much acting as a noise floor for various ambient emitters. If I were to use a normal 2D sound, I'd have no control over where it plays in the scene. If I used a 3D sound, my noise floor would be spatialised and would be affected by the player's orientation. To solve this, I used a box collider for each ambient area. This collider is used to trigger a 2D audio source when the player is inside of it. Simple. As the player exits the collider, the script attached calculates the distance between the player character and the closest point of the collider box. This distance is mapped to a value between 0 and 1, which drives the ambiences volume. As the player leaves the collider and walks away, the ambience gets quieter. Perfect! When combined with the other area colliders, a little tweaking in volume and distances, you end up with a smooth crossfade between areas.

It's worth noting that the script on these colliders is running in Unity's Update function and is, therefore, being called once every frame. To be more efficient, I could run this in a Coroutine with a WaitForSeconds yield instruction (so it's not called once per frame!) but for this project, Update will be fine.

Here's an example below. In the next blog post, I'll be writing up how I approached the ambient emitters and how I implemented them in random containers :)