Guidance / Cookbook
Per-Zone Reverb
The “wet path” sibling of the occlusion section. SFX voices send a copy of their dry signal to a per-zone reverb bus; each bus’s character is defined by its ReverbSendBus asset, which is the single source of truth (the zone only decides which bus a voice sends to). See Manual chapter 15 for the architecture.
🧱 Prerequisite: the Occlusion Slot Pool must already be authored. Reverb sends are written into the voice’s occlusion slot — no slot, no sends. If you haven’t done it yet, jump to Occluding SFX Through Geometry → One-Time Project Setup first. Come back here once the layout exists.
⚠️ Silent failures to know up front
- A bus’s character lives on its
ReverbSendBusasset, not the zone. A new bus’sRoomis0mB (millibels; full level), so it’s audible once generated. A bus whoseRoomhas been turned down to-10000mB is silent until you raise it. Tagging a zone and pointing itsReverb Busat that asset routes voices there, but the sound comes from the asset.- The
Reverb Busfield onAudioZonewants the mixer group reference inside the SendBus asset — not the SendBus asset itself. Drag from the SendBus’sReverbBusfield, not from the Project window.AudioManager.Reverb Send Bus Registrymust be assigned. Without it, the registry is empty and nothing routes.- After adding a new bus, re-run the Occlusion Layout Builder so existing slots get the new bus’s Send parameter authored. Skipping this means existing containers can’t send to the new bus.
Setup Path
Follow these in order. Each recipe assumes the previous one is done.
- Author a Reverb Send Bus — once per acoustic archetype (small room, large hall, outdoors).
- Tag a Zone to Use This Bus — for each physical room in your scene.
- Send an SFX Container Into the Reverb — flip the per-sound
Allow Reverb Sendflag. - (Optional) Override Routing for Music or Narration — for sounds with authored, non-zone-driven character.
- (Optional) Tune a Bus’s Character While Editing — iteration workflow.
Recipe: Author a Reverb Send Bus
📋 What: Create a single reverb bus and wire it up so voices physically in a tagged zone send to it.
🎯 Use Case: First step for any per-zone reverb in the project. Authoring is one-time per acoustic space.
Asset Setup
1. Create the SendBus asset:
- Project ▸ Create ▸ Audio System ▸ Reverb Send Bus
- Name it after the room:
Reverb_Bathroom(the asset name becomes the bus id and the basis for exposed parameter names)
2. Configure the SendBus:
- Reverb Mixer: drag in your voice mixer asset (the same one assigned to AudioManager ▸ Voice Mixer)
- Leave Reverb Bus blank — it auto-fills on Generate
- Leave Output Destination blank for single-mixer setups (the wet tail flows up the group hierarchy naturally)
- (Optional) Parent Group: assign a
ReverbsWetreturn-bus group if you use the DAW-style convention — Generate will nest this SendBus under it - Parametric reverb — Basic:
- Dry Level: -10000 (the default; SendBus groups are wet-only by design)
- Room: 0 (overall wet gain; lower to attenuate)
- Decay Time: tune for the space — bathroom ≈ 0.8 s, cathedral ≈ 5 s, cave ≈ 4 s
- Reverb Level: 200 (Unity’s SFX Reverb default)
3. Generate:
- Select the SendBus asset
- In the inspector, click Generate Mixer Group
- Console should log success: “Generated ‘Bathroom’: groups +1, effects +1, exposed params +6, values applied 14/14, output set: no”
- The mixer now has a
Bathroommixer group with an SFX Reverb effect;Reverb_Bathroom_Wet,_Decay,_Room,_RoomHF,_DecayHFRatio,_Reflectionsare exposed for the runtime driver
4. Register the bus in the project registry:
- Open Window ▸ Audio System ▸ Reverb Send Buses
- If no registry exists yet, create one: Project ▸ Create ▸ Audio System ▸ Reverb Send Bus Registry
- Drop the registry into AudioManager ▸ Reverb Send Bus Registry
- Click Refresh in the window — your new SendBus appears in the list
5. Sanity-check:
- Click Validate Wiring on the SendBus asset. It should say “Wiring OK.”
✅ Result: The reverb bus exists on the mixer, exposes the right runtime parameters, and is registered. Voices won’t send to it yet — that requires tagging an AudioZone (next recipe).
Recipe: Tag a Zone to Use This Bus
📋 What: Tell an AudioZone “voices in here send to this reverb bus.”
🎯 Use Case: After authoring a SendBus, every zone that should produce that bus’s reverb needs to be tagged.
Asset Setup
1. Select the AudioZone GameObject in your scene.
2. In the AudioZone component:
- Reverb Bus: drag in the
Reverb_BathroomSendBus’sReverbBusfield (open the SendBus inspector and drag from there — it’s the mixer group reference). This is the only reverb setting on the zone.
The zone has no reverb character of its own. How the room sounds (Room, Room HF, Decay Time, Decay HF Ratio, Reflections, Reverb Level) is set on the Reverb_Bathroom SendBus asset from the previous recipe. To make two rooms sound different, give them separate SendBus assets.
What Happens at Runtime
- Source-side: voices in this zone whose container has
Allow Reverb Send = ✓send a copy of their signal toReverb_Bathroomat their authored level. The send level scales by the listener’s audibility to the zone (1.0 same-zone, <1 through portals). - Listener-side: the bus’s six runtime-driven parameters are written from the SendBus asset every reverb-sends tick. They don’t change with where the listener stands; only the send level does.
✅ Result: The bathroom zone is now acoustically alive. Voices in the bathroom contribute to the bathroom bus, which sounds the way its SendBus asset is authored.
Recipe: Send an SFX Container Into the Reverb
📋 What: Flip an existing SFX container into the per-zone reverb path.
🎯 Use Case: Take a gunshot / footstep / impact container and have its voices contribute to the reverb of the room they’re fired in.
Asset Setup
On the AudioContainer:
- Allow Reverb Send: ✓
- Reverb Send Level Db: per-sound tuning
- 0 dB — full wet contribution. Right for big impacts (gunshots, explosions) that should ring out the room.
- -6 dB — half-loud wet contribution. Good baseline for most SFX.
- -12 dB — quiet wet contribution. Right for small detail sounds (footstep grain, weapon foley) that should colour the mix but not dominate the reverb.
- -80 dB — effectively silent. Use
Allow Reverb Send = offinstead if you want zero contribution.
- Static Emitter: ✓ if the voice doesn’t move during its lifetime (impacts, stingers, fixed-prop ambiences). Off for vehicle sounds, footsteps parented to a character, etc.
What Happens at Runtime
- The container’s
Use OcclusionandAllow Reverb Sendflags both feed the same slot decision: the voice acquires an OcclusionSlot on play (see chapter 14 §14.4). WriteReverbSendsImmediateruns synchronously when the voice is configured, so its very first audio frame already has the correct send level.- The reverb-sends driver re-evaluates every ~50 ms while the voice is playing — sends respond to listener motion (audibility changes) even on static emitters.
✅ Result: This sound, fired anywhere in the world, contributes to whichever zone’s reverb bus its source position is in — without any code changes.
Recipe: Override Routing for Music or Narration
📋 What: Make a specific container always send to a fixed reverb bus, regardless of where the listener stands or what zone the source is in.
🎯 Use Case: Music that should always carry a “cathedral choir” reverb. Narrator VO that should always have a tight studio reverb. UI tails that should bypass per-zone routing. Anything whose acoustic character should be authored, not derived.
Asset Setup
On the AudioContainer:
- Allow Reverb Send: ✓
- Explicit Reverb Bus: drag in the target
ReverbSendBusasset - Reverb Send Level Db: as desired
What Happens at Runtime
Per-tick, the reverb-sends driver sees the explicit bus reference and takes the explicit-bus short-circuit:
- The named bus gets the container’s
ReverbSendLevelDbat all times (no audibility or membership scaling). - Every other registered bus is silenced for this voice.
- Source zone resolution is bypassed entirely.
The voice’s character is now authored, not zone-derived. Listener motion changes nothing about the routing.
✅ Result: A music container that always plays with cathedral reverb, regardless of whether the player is inside a cathedral or outdoors.
Recipe: Tune a Bus’s Character While Editing
📋 What: Iterate on a reverb’s sound by tweaking values on the SendBus asset and pushing them to the mixer without re-running the full Generate.
🎯 Use Case: Dialing in a room’s character during gameplay-tuning sessions.
Workflow
Option A — Edit the SO, push to mixer:
- Select the
ReverbSendBusasset - Tweak Decay Time, Room HF, Reflections Level, etc. on the SO
- Click Apply Params → Mixer
- Enter play mode and listen
Use when the SO is your source of truth. Apply Params skips the group/effect/expose work and only writes the parametric values — fast iteration.
Option B — Edit the mixer window, pull back to SO:
- Open the Audio Mixer window, select the SendBus’s group
- Edit the SFX Reverb effect’s parameters directly (snapshot must be the target snapshot, which is the default for fresh mixers)
- Back on the SendBus asset inspector, click Pull Params ← Mixer
- The SO now reflects your mixer-window tweaks
Use when the mixer window’s UI is more convenient (it has the per-parameter sliders right there). Pull ensures the SO catches up so re-running Generate later doesn’t undo your work.
⚠️ Caveat: Generate always overwrites the mixer effect’s parameter values from the SO. If you’ve been tuning in the mixer window without pulling, Generate will wipe your tweaks. The safe workflow is Edit-mixer → Pull → Generate, or just stay on Option A.
✅ Result: Live iteration on reverb character without breaking the schema or losing changes.
Troubleshooting
“My voice has Allow Reverb Send = ✓ but I hear no wet tail.”
- Confirm
AudioManager.ReverbSendBusRegistryis assigned and contains at least one bus. - Confirm the source’s zone has its
ReverbBusfield set to a bus that’s in the registry. - Confirm the bus’s
ReverbSendBusasset isn’t silent: a parametric bus withRoomat -10000 mB produces no tail — raise it toward 0 (the default). A convolution bus with noImpulse Responseassigned is likewise silent. - Confirm the listener can reach the source’s zone (unreachable zones produce audibility = 0).
- Confirm the container’s
Mixer Groupis a bus that appears in the Occlusion Layout’s bus list — without a slot, there are no Send level params to write to.
“Several zones share one bus and they all sound identical.”
- This is by design as of the source-of-truth unification: a bus has one acoustic identity, defined by its
ReverbSendBusasset, regardless of which zone routed the voice to it. Per-zone variation on a shared bus is no longer supported. - If you need Cathedral and Cathedral_Crypt to sound different, give them separate
ReverbSendBusassets and point each zone’sReverbBusat its own.
“I added a new ReverbSendBus but it doesn’t appear in the dropdowns.”
- Open Window ▸ Audio System ▸ Reverb Send Buses and click Refresh. The registry only updates when refreshed.
- After refreshing, re-run the Occlusion Layout Builder so existing occlusion slots get the new bus’s Send param authored.
“Voices on this bus sound dry on the first frame, then reverb kicks in.”
- This was a previous bug — voices used to play dry for up to one driver tick (50 ms) before sends were written. The fix is
WriteReverbSendsImmediate, which is called synchronously byAudioContainer.ConfigureAudioSource. If you’re seeing this on a custom playback path that bypassesConfigureAudioSource, callWriteReverbSendsImmediate(voice, container)yourself right after settingvoice.OcclusionSlot.
“My mixer-window tweaks vanish whenever I re-Generate.”
- Generate is non-destructive only if the SO already matches the mixer. Click Pull Params ← Mixer first to sync the SO to your live tweaks, then Generate becomes a no-op on those values. Or stay in the SO-first workflow and use Apply Params → Mixer for iteration.
From the Pepper.SFX 3.1 guides (USER_GUIDE.md). Something wrong or unclear? Tell me.