Rain outside a house shouldn’t sound the same in the hallway as on the porch. Indoors you hear it through the open window, quieter, duller and from the window’s direction; shut the door to that room and it fades further. Pepper.SFX models this with zones and portals, and routes long-running ambient loops through them.
How it works
- An Audio Zone is a room: a GameObject with one or more trigger BoxColliders. An L-shaped room is one zone with two boxes.
- An Audio Portal is an opening between two zones: a doorway, a window, a vent. It sets how much gets through open (Base Transmission, Open Low Pass Hz) and closed (Closed Transmission, Closed Low Pass Hz).
- A portal can follow a door. Any MonoBehaviour that implements
IPortalDoorSource(anOpenProgressfrom 0 to 1 and anOnChangedevent) drives it, so Pepper doesn’t need to know how your doors work. Half open gives values halfway between. - An Ambient Source declares a looping clip in a zone. The Propagation Manager finds the best path from that zone to the listener’s, adding up the loss at each portal and keeping the lowest cutoff, and plays the loop from a pooled emitter at the portal you hear it through. Walk along the wall and the rain slides along the window.
- In a doorway you hear a blend of both sides, so there’s no snap at the threshold.
- The manager creates itself in Play mode, solves 15 times a second (Solve Rate Hz) and smooths volume, cutoff and position every frame.
- One-shot sounds can use the same rooms: tick Use Propagation on a container and a knock behind a closed door is muffled through the portals. This needs the occlusion slots.
Example
A door that swings open and shut and tells its portal as it moves.
using System;
using UnityEngine;
using AudioSystem.Propagation;
public class AudioDoor : MonoBehaviour, IPortalDoorSource
{
[SerializeField] private float swingSeconds = 0.8f;
[SerializeField] private float openAngle = 90f;
private float progress; // 0 = closed, 1 = open
private bool wantOpen;
public float OpenProgress => progress;
public event Action OnChanged;
public void Open() => wantOpen = true;
public void Close() => wantOpen = false;
void Update()
{
float target = wantOpen ? 1f : 0f;
if (Mathf.Approximately(progress, target)) return;
progress = Mathf.MoveTowards(progress, target, Time.deltaTime / swingSeconds);
transform.localRotation = Quaternion.Euler(0f, progress * openAngle, 0f);
OnChanged?.Invoke(); // the portal re-solves now, not on the next tick
}
}
Without OnChanged, the portal still picks up the change on the next solve, up to about 67 ms later.
Setting it up
- For each room, make a GameObject and add Audio > Propagation > Audio Zone. It adds a trigger BoxCollider; size it to the room. For the outdoors, set Activation Radius to Infinity so it’s never culled.
- At each opening, add Audio > Propagation > Audio Portal to a GameObject. Size its box to span the opening and overlap both rooms’ boxes by at least 5 cm. Set Zone A and Zone B (or tick Auto Detect Zones), and point the object’s +Z through the opening.
- For a door, drag a component that implements
IPortalDoorSourceinto the field under the portal’s Door Source heading. Leave it empty for openings that are always open. - Add Audio > Propagation > Ambient Source to an object in the zone the sound comes from. Set Source Zone, Looping Clip and Ambience Mixer Group.
- Add Audio > Propagation > Audio Listener Zone Tracker to the player object that has the Collider, not to the camera with the AudioListener.
- Press Play and walk through. Select the Propagation Manager in the Hierarchy to see the listener’s zone and the active emitters.
Good to know
- Web builds: beds still route through zones, portals and doors, but aren’t muffled and get no reverb: the emitters use Unity’s Low Pass and Reverb filter components, which Web audio doesn’t support.
- Ambient emitters sit outside Pepper’s voice pool, capped by Max Ambient Emitters (16); past the cap, the farthest goes silent.
- A source is heard through its single best path unless you raise Max Paths Per Source (up to 6), at one emitter per path.
- Clutter inside a room doesn’t block ambient beds unless you tick Enable Obstruction on the Propagation Manager.
- Beds take on the reverb of the room you’re in, from that zone’s Reverb Send Bus.
- A bad loop point in the clip clicks every time round. Sound doesn’t bend round corners, so split large open spaces into more zones.