Audio Occlusion in Unity: Snapshots vs. Raycasting

Omer FaranOmer Faran
4 min read

When sound passes through walls, it becomes muffled. This is called audio occlusion. Unfortunately, Unity cannot simulate this effect automatically (yet), but it’s easy enough create manually! So In this tutorial, we'll explore two main ways to simulate occlusion in Unity, one is very simple and straightforward, and another more complex but flexible way (with caveats):

  1. Using AudioMixer Snapshots

  2. Using Physics.Raycast + AudioLowPassFilter


Option 1: Audio Occlusion Using Snapshots

This method is great for simple room setups, where sounds become clean (without any effects) when the player enters a room and muffled when the player is outside.

We'll use a radio in a room as an example, and demonstrate how its sound changes depending on whether the player is inside or outside the room.

Step 1: Add a radio sound source

  • Create an empty GameObject. You can name it Radio

  • Add an AudioSource component to it.

  • Assign a looping audio clip (any audio will do)

  • Set Spatial Blend to 3D

  • You can mess around with Max Distance, something like 15 is probably good.

Step 2: Create an Audio Mixer

  • Create an audio mixer if you haven't yet (Assets > Create > Audio Mixer)

  • Right click the Master group => Create Child Group => name it SFX

Step 3: Create Snapshots

  • In the Mixer window, click Snapshotד

  • Click the + button twice to create two snapshots: Clear and Muffled

Configure Muffled snapshot:

  • Select the Muffled snapshot

  • Click on the SFX group

  • In the Inspector, check Low Pass Filter and set cutoff frequency to 800 Hz. The value here is again something to mess around with, it depends on the thickness of the wall and so on.

Step 4: Assign the AudioSource to the Mixer

  • Select the Radio GameObject

  • In the AudioSource component, set Output to SFX

Step 5: Create a trigger zone for the room

  • Create an empty GameObject called RoomTrigger

  • Add a Box Collider and check Is Trigger

  • Scale and position it so it fills the room

Step 6: Add a script to trigger the correct snapshot

Create a new script called OcclusionTrigger.cs:

using UnityEngine;
using UnityEngine.Audio;

public class OcclusionTrigger : MonoBehaviour
{
    public AudioMixerSnapshot clearSnapshot;
    public AudioMixerSnapshot muffledSnapshot;
    public float transitionTime = 0.5f;

    private void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("Player"))
            clearSnapshot.TransitionTo(transitionTime);
    }

    private void OnTriggerExit(Collider other)
    {
        if (other.CompareTag("Player"))
            muffledSnapshot.TransitionTo(transitionTime);
    }
}

Step 7: Setup the Player and assign snapshots

  • Make sure the Player GameObject has a Collider and is tagged as Player

  • Assign the Clear and Muffled snapshots in the Inspector for the RoomTrigger

Done! Now when the player enters the room, the sound becomes clear. When they step outside, it’s muffled.


Option 2: Audio Occlusion Using Raycasting

This method gives more precise occlusion and works per sound source. It’s ideal for enemies or moving NPCs. Just keep in mind that raycasting every frame can get expensive if overused, so it’s best to apply this method selectively to important sound sources only.

We’ll use Physics.Raycast to check if there's a wall between the sound source and the listener, and apply a lowpass filter if blocked.

Step 1: Create the sound emitter

  • Create a GameObject called Enemy

  • Add an AudioSource and assign a looping sound

  • Set Spatial Blend to 3D

  • Add an AudioLowPassFilter component

  • Set the cutoff frequency to 22000 Hz (default clear sound)

Step 2: Create the script

Create a new script called AudioOcclusion.cs:

using UnityEngine;

[RequireComponent(typeof(AudioLowPassFilter))]
public class AudioOcclusion : MonoBehaviour
{
    public Transform listener;
    public LayerMask occlusionMask;
    public float clearCutoff = 22000f;
    public float muffledCutoff = 800f;
    public float transitionSpeed = 5f;

    private AudioLowPassFilter lowPass;

    void Start()
    {
        lowPass = GetComponent<AudioLowPassFilter>();
    }

    void Update()
    {
        Vector3 direction = listener.position - transform.position;
        float distance = direction.magnitude;

        if (Physics.Raycast(transform.position, direction, out RaycastHit hit, distance, occlusionMask))
        {
            lowPass.cutoffFrequency = Mathf.Lerp(lowPass.cutoffFrequency, muffledCutoff, Time.deltaTime * transitionSpeed);
        }
        else
        {
            lowPass.cutoffFrequency = Mathf.Lerp(lowPass.cutoffFrequency, clearCutoff, Time.deltaTime * transitionSpeed);
        }
    }
}

Step 3: Assign references

  • Drag the Main Camera (which should have the AudioListener) into the listener field

  • Set the occlusionMask to include layers that should block sound. If you haven't set up custom layers for obstacles, just leave it as Default and make sure the wall (or walls) are on that layer.

  • Also make sure the walls have colliders

That’s it! Now the enemy sound will get muffled when a wall is between it and the player.


Summary

  • Snapshots are best for room based transitions (inside/outside)

  • Raycasting is more flexible and realistic, especially for moving sources or complex environments, but it's also more expensive, so use it with care

  • You can mix both approaches in one project for performance and realism

0
Subscribe to my newsletter

Read articles from Omer Faran directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Omer Faran
Omer Faran