Good positional sound tells the player where danger is before they see it. Bad positional sound is either flat (everything at the same volume no matter where it is) or wildly loud and quiet as you walk around. This Unity 3D audio guide covers everything you need for convincing spatial sound: the Spatial Blend slider, rolloff curves and distances, spread and doppler, Audio Reverb Zones, simple occlusion with raycasts, and pooling one-shot sounds so explosions and footsteps don’t create garbage or cut each other off.
Listener, Sources and Spatial Blend
Unity audio has two parts. The Audio Listener is the “ears”, normally on the main camera. Each Audio Source plays a clip from its GameObject’s position. There must be exactly one active Audio Listener in the scene; two gives a warning and unpredictable results.
The setting that makes a source 3D is Spatial Blend:
- 0 (2D): the sound plays at the same volume and pan regardless of position. Use it for music, UI clicks and the player’s own voice.
- 1 (3D): volume and stereo pan depend on the source’s position relative to the listener. Use it for anything in the world.
- In between: blends the two, which can be nice for ambience that should be slightly directional but never vanish.
The single most common “3D audio doesn’t work” problem is leaving Spatial Blend at its default of 0. New Audio Sources start as 2D.
Where to put the listener: on the camera works for first-person games. In third-person games the camera is several metres behind the character, so sounds to the character’s left can feel wrong. A common fix is placing the listener on the player (or between player and camera) while keeping the camera’s rotation, so panning follows the view.
Also use mono clips for 3D sounds. Stereo clips can be spatialized, but their baked-in stereo image fights the positional panning. Tick Force To Mono in the clip’s import settings for world sounds.
Rolloff Curves and Min/Max Distance
Expand 3D Sound Settings on the Audio Source. Rolloff controls how volume falls off with distance:
- Min Distance: inside this radius the sound plays at full volume. Make it larger for loud sources (an explosion might be 10 m) and small for quiet ones (a ticking clock at 0.5 m).
- Max Distance: for Logarithmic rolloff, the volume stops dropping here, but it does not go silent. For Linear rolloff, it reaches zero here.
- Logarithmic Rolloff (default): realistic, loud close up and a long quiet tail. The catch is that the tail never reaches zero, so a source 500 m away is still faintly audible and still uses a voice.
- Linear Rolloff: easy to reason about, reaches silence at Max Distance. Less realistic but very predictable for gameplay.
- Custom Rolloff: draw your own curve in the graph. Great for “realistic near, but definitely silent by 40 m”.
A practical recipe: use Custom Rolloff, shape the start like the logarithmic curve, then pull the end down to zero at Max Distance. The graph also contains curves for Spatial Blend, Spread and Reverb Zone Mix against distance, so you can make a sound become more 2D or more reverberant as it gets further away.
You can set these from code when spawning sources:
AudioSource src = GetComponent<AudioSource>();
src.spatialBlend = 1f;
src.rolloffMode = AudioRolloffMode.Linear;
src.minDistance = 2f;
src.maxDistance = 30f;
Spread, Doppler and Priority
- Spread (0 to 360 degrees): at 0 the sound comes from a single point and pans hard. Larger values spread it across speakers. A waterfall or crowd might use 90 to 180 so it doesn’t feel like a pinpoint.
- Doppler Level: pitch shift for moving sources, like a car passing by. It defaults to 1, which can make sounds warble when the camera moves fast. Many games set it to 0 on most sources and keep it only on vehicles and projectiles. There is also a global Doppler Factor in Project Settings > Audio.
- Priority (0 is highest, 256 lowest): Unity plays a limited number of voices at once (Project Settings > Audio > Max Real Voices, 32 by default). When the limit is hit, low-priority sounds are virtualised. Give music and important cues high priority, footsteps and debris low.
- Volume Rolloff and the listener’s velocity: doppler uses the velocity of the Rigidbody or the transform. Teleporting the camera produces a horrible pitch spike for one frame; temporarily set doppler to 0 when you teleport.
Audio Reverb Zones
A Audio Reverb Zone component adds reverb to sounds when the listener is inside its radius. Add one with GameObject > Audio > Audio Reverb Zone.
- Inside Min Distance, the full effect applies. Between Min and Max, it fades. Outside Max, no effect.
- Pick a Reverb Preset like Cave, Hallway, Bathroom or Arena, or choose User to tune parameters.
- Zones are spheres, so cover irregular rooms with several overlapping zones. Where zones overlap, Unity blends them.
- Each Audio Source has a Reverb Zone Mix value (and a distance curve) controlling how much reverb it receives. Set it to 0 for UI and music.
Reverb zones are cheap and easy. For more control, put a reverb effect on an Audio Mixer group and change its wet level with mixer snapshots when the player enters a trigger. Our Audio Mixer volume slider guide covers mixer setup.
Basic Audio Occlusion
Unity’s built-in audio has no automatic occlusion, so a monster behind a concrete wall sounds as clear as one in the open. A simple approach: raycast from the listener to each important source, and if geometry is in the way, lower the volume and muffle it with an Audio Low Pass Filter.
using UnityEngine;
[RequireComponent(typeof(AudioSource), typeof(AudioLowPassFilter))]
public class SimpleOcclusion : MonoBehaviour
{
[SerializeField] LayerMask occluders;
[SerializeField] float openCutoff = 22000f;
[SerializeField] float blockedCutoff = 1200f;
[SerializeField] float blockedVolume = 0.5f;
[SerializeField] float smoothing = 8f;
[SerializeField] float checkInterval = 0.1f;
AudioSource source;
AudioLowPassFilter lowPass;
Transform listener;
float baseVolume, timer;
bool blocked;
void Awake()
{
source = GetComponent<AudioSource>();
lowPass = GetComponent<AudioLowPassFilter>();
baseVolume = source.volume;
var l = FindAnyObjectByType<AudioListener>();
if (l != null) listener = l.transform;
}
void Update()
{
if (listener == null || !source.isPlaying) return;
timer -= Time.deltaTime;
if (timer <= 0f)
{
timer = checkInterval;
blocked = Physics.Linecast(listener.position, transform.position, occluders,
QueryTriggerInteraction.Ignore);
}
float k = 1f - Mathf.Exp(-smoothing * Time.deltaTime);
lowPass.cutoffFrequency = Mathf.Lerp(lowPass.cutoffFrequency,
blocked ? blockedCutoff : openCutoff, k);
source.volume = Mathf.Lerp(source.volume,
blocked ? baseVolume * blockedVolume : baseVolume, k);
}
}
Only put this on sources that matter (enemies, important objects), set the occluders mask to walls only, and check a few times per second rather than every frame. If raycasts and layer masks are new, see our raycast tutorial. For true geometry-based occlusion and propagation, middleware like Steam Audio or FMOD with a spatializer is the next step.
🎧 Want better audio without building it all?
Sound effect libraries, audio managers and occlusion tools on the Asset Store can give you footsteps, impacts and ambience in an afternoon. Here are the tools we rate for indie devs.
Pooling One-Shot Sounds
AudioSource.PlayClipAtPoint is convenient, but it creates and destroys a new GameObject every call, can’t route to a mixer group, and gives you no control over rolloff. For gunshots, impacts and footsteps, pool a set of 3D Audio Sources instead:
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Pool;
using System.Collections;
public class SfxPool : MonoBehaviour
{
public static SfxPool Instance { get; private set; }
[SerializeField] AudioMixerGroup sfxGroup;
[SerializeField] int defaultCapacity = 16;
[SerializeField] int maxSize = 48;
ObjectPool<AudioSource> pool;
void Awake()
{
Instance = this;
pool = new ObjectPool<AudioSource>(Create,
s => s.gameObject.SetActive(true),
s => s.gameObject.SetActive(false),
s => Destroy(s.gameObject),
false, defaultCapacity, maxSize);
}
AudioSource Create()
{
var go = new GameObject("PooledSfx");
go.transform.SetParent(transform);
var s = go.AddComponent<AudioSource>();
s.playOnAwake = false;
s.spatialBlend = 1f;
s.rolloffMode = AudioRolloffMode.Linear;
s.minDistance = 1.5f;
s.maxDistance = 35f;
s.dopplerLevel = 0f;
s.outputAudioMixerGroup = sfxGroup;
return s;
}
public void Play(AudioClip clip, Vector3 position, float volume = 1f, float pitchJitter = 0.08f)
{
if (clip == null) return;
AudioSource s = pool.Get();
s.transform.position = position;
s.clip = clip;
s.volume = volume;
s.pitch = 1f + Random.Range(-pitchJitter, pitchJitter);
s.Play();
StartCoroutine(ReleaseWhenDone(s, clip.length / Mathf.Abs(s.pitch)));
}
IEnumerator ReleaseWhenDone(AudioSource s, float duration)
{
yield return new WaitForSeconds(duration + 0.05f);
pool.Release(s);
}
}
Usage: SfxPool.Instance.Play(hitClip, contact.point);. The small random pitch change stops repeated sounds from feeling robotic. If several identical sounds would play in the same frame (ten bullets hitting a wall), skip duplicates within a few milliseconds. Our object pooling guide explains the ObjectPool API in depth.
Mixer Groups and Spatializer Plugins
Route every source to an Audio Mixer group (Music, SFX, Ambience, Voice) through Output. Spatialization happens on the source before the mixer, so 3D panning still works, and you get volume sliders, ducking and snapshots for free.
For headphone games and VR, a spatializer plugin uses HRTF processing so sounds above, below and behind you are distinguishable, which basic stereo panning can’t do. Install one (Steam Audio, Meta XR Audio, or the Resonance plugin), select it under Project Settings > Audio > Spatializer Plugin, then tick Spatialize on each Audio Source that should use it.
Troubleshooting
Sound is the same volume everywhere
Spatial Blend is 0 (2D). Set it to 1.
Distant sounds never go silent
Logarithmic rolloff never reaches zero. Switch to Linear or Custom and end the curve at zero.
Sound pans the wrong way in third person
The listener is on a camera far from the character. Move the listener closer to the player.
Pitch warbles when the camera moves
Doppler. Set Doppler Level to 0 on that source or lower the global Doppler Factor.
Some sounds randomly don’t play
You’ve hit the voice limit and they were virtualised. Raise priority on important sounds, lower it on spam, and stop distant sounds.
Reverb zone has no effect
Reverb zones check the listener’s position, not the source’s, and the source’s Reverb Zone Mix may be 0.
FAQ
Should 3D sound clips be mono?
Yes. Mono clips spatialize cleanly. Enable Force To Mono in the import settings.
Can I have two Audio Listeners for split-screen?
No, Unity supports one active listener. For split-screen, use one listener between players or treat most sounds as 2D.
Is PlayClipAtPoint bad?
It’s fine occasionally, but it allocates a GameObject per call and can’t use a mixer group. Pool sources for frequent sounds.
Does Unity do audio occlusion automatically?
No. Use raycasts with a low-pass filter, or middleware like Steam Audio or FMOD.
What is a good Max Distance?
It depends on scale, but 20 to 50 m suits most character-scale games. Huge explosions might use 100 m or more.
What is spatialBlend in Unity?
AudioSource.spatialBlend (the Spatial Blend slider) sets how 3D a sound is: 0 is fully 2D, the same volume and pan everywhere; 1 is fully 3D, panned and faded by distance from the Audio Listener. Set it to 1 for positional sounds, in the Inspector or with source.spatialBlend = 1f;.
Reader questions
Asked by readers of this article and answered by AI. Behavior can differ between Unity versions, so test in yours.




Leave a Reply