A guard hears the player through a concrete wall. A machine behind a closed door sounds almost as clear as one in the same room. A gunshot becomes quieter when the player steps behind a pillar, but its tone never changes. These are usually not problems with the sound file itself. They are signs that the game is not yet describing what sits between the sound source and the listener.
Two related systems solve different parts of this problem. Occlusion describes sound travelling through or around a barrier between the source and listener. Obstruction usually describes a partial blockage along the direct path, where the sound may still be audible but its high frequencies or level are reduced. Engines and middleware do not always use these terms identically, so decide what each label means in your project before wiring up the logic.
The practical goal is not to simulate every reflection in a room. It is to make a player reliably hear the difference between a nearby open sound, a sound behind a thin obstacle, and a sound sealed behind a wall or closed door.
Start with three listening tests, not a complicated audio system
Build a small test space with a listener, a looping sound source, and three kinds of barrier: a thin panel, a solid wall, and a door that can open and close. Keep the source clip and playback level the same throughout. First listen with no barrier, then place each barrier between the source and listener. If you cannot clearly describe the intended difference in plain language, it will be difficult to tune the system by ear later.
- Open path: the sound keeps its normal direct level and tone, apart from ordinary distance attenuation.
- Partial obstruction: the direct sound is weakened or softened, but it still feels close to the listener.
- Strong occlusion: the barrier substantially reduces the direct sound and often removes more high-frequency detail. Some low-frequency energy may remain, depending on the material and the style of the game.
Use a loop with a steady spectrum for initial tuning—a fan, engine hum, or sustained noise is easier to compare than a very short impact. Then repeat the test with speech, footsteps, and a sharp transient. A filter that sounds plausible on a continuous hum can make dialogue unintelligible or turn a gunshot into a dull thump.
Choose how the game will detect a barrier
The simplest runtime method is a raycast from the listener toward each active sound source. If the ray hits a world collider before it reaches the source, the path is blocked. This is a useful first pass because it is easy to debug and does not require custom geometry analysis. In a Unity project, for example, the query can use a dedicated layer mask so triggers, pickup zones, and decorative colliders do not accidentally muffle sounds. If you have not yet set up source and listener placement, first work through the step-by-step guide to 3D positional audio in Unity; occlusion builds on top of that foundation rather than replacing it.
One ray is not a complete model of sound propagation. A character may hear a source around the edge of a doorway even when the direct ray hits a wall. A large source, such as a waterfall or crowd, occupies more than a single point. You can improve the result later with several sample rays, doorway/portal logic, room connectivity, or an audio middleware occlusion system. Start with one ray because it gives you a visible, testable baseline.
Make collision queries match audio intent
Create a layer such as AudioOccluder and assign it only to objects that should affect sound. Decide how to treat glass, fences, foliage, thin partitions, and open door frames. A physical collider may be necessary for gameplay but irrelevant to sound; conversely, a sound-blocking surface may need an audio-only collider. Do not let every collider in the level silently become an acoustic wall.
Also check the ray direction and distance. The ray should start at the listener’s ear or camera-adjacent listening point and point toward the source. If the source is inside a collider, or the listener starts inside a wall collider, a basic ray query may not produce the result you expect. Visualize the ray in the editor and test both sides of every doorway.
A minimal Unity implementation
The following example demonstrates a straightforward first pass for one AudioSource. Attach it to the same object as the source's AudioSource, assign the listener transform, and select the layers that should block sound. Add an AudioLowPassFilter to that source object. The script checks the direct path and smoothly blends between an open and blocked state instead of changing the sound abruptly every frame.
using UnityEngine;
[RequireComponent(typeof(AudioSource))]
[RequireComponent(typeof(AudioLowPassFilter))]
public class SimpleAudioOcclusion : MonoBehaviour
{
[SerializeField] private Transform listener;
[SerializeField] private LayerMask occluderLayers;
[SerializeField, Range(0f, 1f)] private float blockedVolume = 0.55f;
[SerializeField, Range(500f, 22000f)] private float blockedCutoff = 1800f;
[SerializeField] private float blendSpeed = 5f;
private AudioSource source;
private AudioLowPassFilter lowPass;
private float openCutoff;
private float openVolume;
private void Awake()
{
source = GetComponent<AudioSource>();
lowPass = GetComponent<AudioLowPassFilter>();
openCutoff = lowPass.cutoffFrequency;
openVolume = source.volume;
}
private void Update()
{
if (listener == null) return;
Vector3 toSource = transform.position - listener.position;
float distance = toSource.magnitude;
bool blocked = distance > 0.01f &&
Physics.Raycast(listener.position, toSource.normalized,
distance, occluderLayers, QueryTriggerInteraction.Ignore);
float targetVolume = blocked ? openVolume * blockedVolume : openVolume;
float targetCutoff = blocked ? blockedCutoff : openCutoff;
float blend = 1f - Mathf.Exp(-blendSpeed * Time.deltaTime);
source.volume = Mathf.Lerp(source.volume, targetVolume, blend);
lowPass.cutoffFrequency = Mathf.Lerp(
lowPass.cutoffFrequency, targetCutoff, blend);
}
}
This is intentionally a teaching example, not a universal production component. It treats any hit as the same amount of blockage, stores the source's starting volume as its open level, and checks only one listener and one ray. If another system also changes the source volume, the two systems can fight each other. For production, calculate an occlusion multiplier separately and apply it through a mixer or a dedicated audio-control layer rather than repeatedly overwriting a value owned by gameplay code.
The values blockedVolume and blockedCutoff are tuning starting points, not physical constants. A cutoff around 1.8 kHz can make a barrier obvious in a prototype, but it may be far too dark for dialogue or a light wooden screen. Compare the result against the unobstructed sound at the same distance and adjust while listening in the actual game mix.
Occlusion and obstruction should not always use the same response
A single boolean—blocked or not blocked—is easy to implement, but it often creates an unnatural all-or-nothing sound. A thin railing, a wooden door, and a thick stone wall should not necessarily have identical results. You can give each acoustic surface a small profile containing an occlusion strength, low-pass target, and optional volume reduction. When the ray hits a surface, use that profile to choose the target values.
For a simple project, you might classify surfaces as open/porous, light obstruction, and heavy occlusion. A fence may barely affect the sound; a wooden door might lower the level and soften the upper frequencies; a concrete wall may use a stronger reduction. Treat these as artistic categories rather than claims about exact real-world transmission loss. The final result must serve the game's readability and style.
Be careful with volume alone. Lowering a sound by a large amount can make it disappear beneath music and ambience, while filtering too aggressively can remove the identity that tells the player what is happening. Often a moderate level reduction plus a less bright tone reads better than either change used at maximum strength.
Prevent rapid switching at doorframes and thin walls
When the listener walks along a wall edge, the ray may alternate between hitting and missing the collider every frame. If the audio parameters follow that result immediately, the sound flickers between filtered and unfiltered states. Smooth interpolation helps, but the detection itself can still chatter around complicated geometry.
Keep separate current and target values for the occlusion amount, then move the current value toward the target over time. Use different response speeds if necessary: a sound can become muffled quickly when a door closes, but recover slightly more slowly as the player peeks through an opening. Avoid making every transition sluggish; a slow filter response can feel disconnected from a door animation or a fast-moving player.
If ray results still flicker, add a short confirmation window or hysteresis. For example, require a blocked result to persist briefly before switching into the blocked state, and use a slightly different threshold to return to the open state. Keep that delay short enough that it does not make fast gameplay feel inaccurate. A small, deliberate transition is usually better than a heavy system that hides every collision edge.
Doors, windows, and sound leaking around corners
A door is not just another static wall if the player can open it. Its acoustic behavior should follow the same state that drives its gameplay or animation. A closed door can apply a stronger filter; a partly open door can reduce that effect; a fully open doorway should generally stop being treated as a solid blocker. If the door collider is removed as soon as the animation starts, make sure the audio state changes at a deliberate point rather than accidentally depending on a collider toggle.
Windows and thin partitions may need a different profile from walls. For games with rooms and corridors, portal-style logic can be more reliable than a single ray: if the source and listener are in connected rooms, the system can estimate how many closed doors or boundaries separate them. This requires more scene setup, but it avoids treating a wall corner as a perfect acoustic seal in every case.
Multi-ray tests are another incremental improvement. Cast a small set of rays toward the source's center and nearby sample points. If every ray is blocked, apply strong occlusion; if only some are blocked, apply a partial result. This works best when the source has a meaningful size or when the game has many doorways and irregular obstacles. More rays cost more CPU, so reserve them for important or nearby emitters rather than blindly checking every sound in a large scene.
Keep distance, reverb, and occlusion as separate controls
Distance attenuation answers “how far away is the source?” Occlusion answers “what blocks the direct path?” Reverb answers “what does the surrounding space do to the sound?” These cues interact, but they should not all be driven by one volume value. A distant sound in the same room should become quieter without automatically sounding as if a wall is between the listener and source. A nearby voice behind a wall may need strong filtering even though its world position is close.
A useful signal flow is: source playback and distance attenuation first, then an occlusion/obstruction control, followed by shared environment or reverb processing where appropriate. Exact routing depends on the engine and mixer design. Keep a way to hear the dry source while debugging; otherwise, a reverb send or compressor can disguise whether your occlusion logic is working.
If the game already has a room ambience system, connect it deliberately rather than adding a large reverb to every blocked sound. A sound behind a wall may be heard indirectly through the environment, but that does not mean every occluded emitter should receive the same reverb amount. If you are building a headset-focused project, this beginner’s guide to spatial audio for VR games covers the broader listener-and-source design around these effects. For the wider scene layer, see the guide to ambient sound in game scenes.
What to test before shipping
Test with a repeatable matrix instead of walking around the level and hoping to notice problems. Use the same source clip and compare these cases from a fixed listener position:
- Source in the same room with a clear path.
- Source at the same distance but behind a thin panel.
- Source behind a thick wall, then moved closer to the wall on the other side.
- Listener crossing a doorway while the source remains still.
- Door opening and closing while a continuous sound plays.
- Several sources at different distances, with only one behind a barrier.
- Dialogue, footsteps, weapon fire, and a steady machine loop processed by the same rules.
Check both headphones and speakers if both matter for your target platform. Listen at normal gameplay volume and at a lower volume, because quiet blocked cues may vanish when the player turns the overall level down. Also test with music and ambience active; a filter that is obvious in solo playback can be imperceptible in a busy mix—or can make a critical cue too hard to recognize.
For debugging, draw the listener-to-source ray, display whether it hit an occluder, and expose the current filter cutoff and attenuation amount in the Inspector or a small debug overlay. If a sound is unexpectedly muffled, you should be able to tell whether the ray hit the wrong collider, a surface profile is too strong, or another mixer effect is responsible.
Common mistakes that make blocked audio sound wrong
- Every collider blocks sound: use an explicit layer mask or acoustic surface component instead of querying the entire physics scene indiscriminately.
- Every barrier sounds identical: distinguish light obstruction from heavy occlusion and tune profiles for gameplay, not just geometry.
- Filtering replaces all other audio logic: preserve distance attenuation and environment sends as separate controls.
- Audio changes instantly: smooth target values and address raycast chatter near edges.
- The script overwrites gameplay volume: apply occlusion as a multiplier or mixer parameter so independent systems do not fight over one property.
- Every source is checked every frame: prioritize important or nearby sounds, update less critical emitters less often, or use the engine/middleware features already available.
- The sound becomes unrecognizable: compare the filtered result against the original and preserve enough tonal identity for players to understand the event.
Occlusion is most successful when it communicates a clear spatial fact without drawing attention to the implementation. Begin with one ray and one continuous sound, make the open and blocked states easy to distinguish, then add material profiles and door behavior only where the level design benefits from them. If you need fresh prototype clips for comparing the states, SfxMaker's sound effect generator can help you create short test sounds before importing them into your project.