Centralized Unity audio middleware for designer-authored sound events.
This package is meant to sit between the sound designer and the programmer:
- The sound designer creates and tunes
AudioEventDefinitionassets. - The programmer calls the
AudioManagerwith an event id. - Gameplay objects notify the audio system, but they do not own
AudioSourceplayback logic.
The package supports both compact and production-scale projects:
- Compact projects: the camera can be both the audio listener and the gameplay audio reference.
- Production projects: the camera can be the listener while a dedicated gameplay transform drives audio logic such as proximity, ambience, combat intensity, or music state.
The package is built around these rules:
| Goal | Package Support |
|---|---|
| Centralize playback | AudioManager owns pooled AudioSource voices, event lookup, playback, mixer parameters, snapshots, and stopping. |
| Keep gameplay code clean | Gameplay code calls the manager with event ids instead of managing AudioSource components directly. |
| Give designers control | AudioEventDefinition assets hold clips, routing, randomization, spatial settings, cooldowns, voice limits, and fades. |
| Support camera-based listening | AudioReferenceRig assigns/registers the listener camera and can ensure it has an AudioListener. |
| Support separate gameplay audio logic | AudioReferenceRig has a separate Logic Reference field used by systems such as AudioDistanceParameterDriver. |
| Support compact setups | Set Reference Mode to CameraOnly when the camera should drive both listening and audio logic. |
| Support larger setups | Set Reference Mode to SeparateListenerAndLogicReference when listening and gameplay audio logic should use different transforms. |
- Open Unity.
- Open
Window > Package Manager. - Press
+. - Choose
Add package from git URL.... - Paste: https://github.com/bitemdev/com.bitemdev.audio-engine.git
- Wait for Unity to import and compile.
The package appears under Packages/BitemDev Audio Engine.
Use this path when someone wants to install the package in an empty project and verify the whole tool without writing code.
- Install the package from the Git URL.
- Open any scene, including a brand-new empty scene.
- Run
Tools > BitemDev > Audio Engine > Create No-Code Demo In Current Scene. - Press Play.
- Use the on-screen
BitemDev Audio Engine Demopanel.
The demo creates:
AudioEngineConfig.assetAudioEventLibrary.asset- Five demo WAV clips generated inside
Assets/AudioEngine/Demo/Clips - Five demo audio events inside
Assets/AudioEngine/Demo/Events - One
AudioManager - One
AudioReferenceRig - One camera listener setup if the scene did not already have one
- One logic reference object
- One green cube for 3D one-shot testing
- One moving cyan sphere for followed loop testing
- One on-screen no-code test panel
The on-screen buttons test:
| Button | What It Tests |
|---|---|
Play 2D UI Event |
Direct event-asset playback, 2D playback, pooling. |
Play Event By Id |
Event library lookup using a string id. |
Play 3D Event At Cube |
Positional playback, camera listener, 3D attenuation. |
Start Follow Loop / Stop Follow Loop |
Looping playback, follow target behavior, handle-based stopping. |
Music A / Music B |
Music playback mode and fade-out replacement. |
Stop All |
Global stop and fade behavior. |
Move follow emitter |
Whether the followed sound updates as its transform moves. |
After using the demo, inspect the generated event assets. They are normal AudioEventDefinition assets and can be edited, duplicated, renamed, or deleted.
Use these steps when testing the tool manually in a fresh Unity project.
Run:
Tools > BitemDev > Audio Engine > Create Default Assets
Unity creates:
Assets/AudioEngine/AudioEngineConfig.assetAssets/AudioEngine/AudioEventLibrary.asset
Purpose:
AudioEngineConfigstores global audio settings.AudioEventLibraryis the list of events the programmer can trigger by id.
Run:
GameObject > BitemDev > Audio Engine > Audio Manager
This creates a scene object named Audio Manager.
Purpose:
- Owns pooled
AudioSourceobjects. - Plays every event.
- Routes events to mixer groups.
- Handles music replacement and fades.
- Handles cooldowns and max voice limits.
- Applies mixer parameters and snapshots.
There should normally be one AudioManager in the first scene or bootstrap scene.
Run:
GameObject > BitemDev > Audio Engine > Audio Reference Rig
Select the new object and assign:
Listener Camera: your Main Camera.Logic Reference: usually the Player object. In an empty test project, create an empty GameObject namedPlayer Referenceand assign it.Reference Mode: choose the setup you want.
Reference modes:
| Mode | Use When | What Happens |
|---|---|---|
CameraOnly |
Compact projects, prototypes, simple scenes | Camera position is used for listening and gameplay audio logic. |
SeparateListenerAndLogicReference |
Projects where camera movement should not drive gameplay audio logic | Camera hears the sound, logic reference drives proximity and parameters. |
Explicit |
Advanced/manual setups | Uses exactly the transforms assigned by code or rig. |
Use SeparateListenerAndLogicReference when camera framing, zoom, or cinematic movement should not affect gameplay audio behavior.
Use CameraOnly when the camera is the only meaningful listener/reference point in the scene.
Open:
Tools > BitemDev > Audio Engine > Open Audio Engine Window
In the window:
- Assign
AudioEventLibrary.assetif it is not already assigned. - Set
Events FoldertoAssets/AudioEngine/Events. - Set
Event Idtoui.test-click. - Press
Create Event Asset. - Select the created event asset.
- In
Clips, set size to1. - Assign any short
AudioClip.
Press Play in Unity. Select the event asset. Press:
Play Through Audio Manager
If the event has a clip and an AudioManager exists in the scene, you should hear it.
Open:
Tools > BitemDev > Audio Engine > Open Audio Engine Window
Press:
Generate AudioEventIds.cs
This creates:
Assets/AudioEngine/Generated/AudioEventIds.cs
Example generated constant:
public const string UI_TEST_CLICK = "ui.test-click";The programmer can now use the constant instead of typing strings.
- Create event assets.
- Assign clips.
- Tune volume, pitch, randomization, spatial settings, cooldowns, and voice limits.
- Validate the library.
- Generate constants.
- Tell the programmer which event ids should be triggered from gameplay.
- Put one
AudioManagerin the bootstrap scene. - Put one
AudioReferenceRigin the scene. - Call the manager from gameplay code.
- Do not put direct
AudioSource.Play()logic in gameplay scripts unless there is a very specific reason.
Use stable, readable ids. Recommended format:
category.object.action
Examples:
ui.confirm
ui.cancel
sfx.player.footstep
sfx.enemy.hit
sfx.weapon.shot
ambience.forest.loop
music.combat
dialogue.npc.greeting
Avoid renaming event ids after programmers start using them. Renaming an id requires updating code or regenerating constants.
Create from:
Create > BitemDev > Audio Engine > Audio Event
Or use the Audio Engine window.
Purpose:
An AudioEventDefinition is one playable sound event. It can contain one clip or several variations.
| Field | Purpose | Example |
|---|---|---|
Event Id |
Stable id used by code and generated constants. | sfx.player.jump |
Category |
Organizational label. Does not change playback by itself. | Sfx, Music, Ambience, Dialogue, Ui |
Playback Mode |
How the event behaves. | OneShot, Loop, Music |
Spatial Mode |
Whether the event is 2D or 3D. | UI = TwoD, explosion = World3D |
Output Mixer Group |
Audio Mixer group for routing. | Master/SFX, Master/Music |
Clip Selection Mode |
How to pick clips from the list. | Random or Sequential |
Clips |
AudioClip variations. | 5 footstep clips |
Each clip entry has:
| Field | Purpose |
|---|---|
Clip |
The actual AudioClip. |
Weight |
Random selection weight. Higher means more likely. Only used in Random mode. |
Volume |
Per-clip volume multiplier. Useful when one variation is louder. |
Pitch |
Per-clip pitch multiplier. Useful when one variation needs correction. |
Example:
- Footstep 1 weight
1 - Footstep 2 weight
1 - Footstep 3 weight
0.5
Footstep 3 plays less often.
| Field | Purpose | Recommended Use |
|---|---|---|
Volume |
Base event volume. | Start at 1, lower if needed. |
Pitch |
Base pitch. | Keep 1 unless designing variation. |
Random Volume |
Adds random volume offset. | Footsteps, cloth, impacts. |
Random Pitch |
Adds random pitch offset. | Footsteps, impacts, repeated UI sounds. |
Priority |
Unity voice priority. Lower number is more important. | Music/dialogue lower number, tiny debris higher number. |
Ignore Listener Pause |
Plays even when AudioListener.pause is true. |
Pause menu UI. |
Delay |
Starts playback after seconds. | Delayed stingers. |
Fade In Seconds |
Fades in when starting. | Music, ambience loops. |
Fade Out Seconds |
Default fade when stopped/replaced. | Music, ambience loops. |
Only matter when Spatial Mode is not TwoD.
| Field | Purpose | Recommended Use |
|---|---|---|
Spatial Blend |
0 = 2D, 1 = full 3D. |
Usually 1 for world sounds. |
Min Distance |
Full volume range. | 1 to 3 for small sounds. |
Max Distance |
Distance where attenuation stops. | Depends on scene scale. |
Rolloff Mode |
Distance attenuation curve. | Logarithmic is a good default. |
Doppler Level |
Pitch shift from movement. | Use carefully. Often 0 or low in stylized games. |
Spread |
Stereo spread for 3D source. | Usually 0 for point sounds. |
Reverb Zone Mix |
How much the source feeds reverb zones. | 1 default. |
Spatialize |
Enables Unity spatializer plugin if configured. | Only if project uses a spatializer. |
| Field | Purpose | Example |
|---|---|---|
Max Voices |
Maximum simultaneous voices for this event. 0 means unlimited until pool limit. |
Footsteps = 4, gunshot = 8 |
Voice Limit Behavior |
What to do when max voices is reached. | Reject new or steal oldest. |
Cooldown Seconds |
Minimum time between plays for this event. | UI spam prevention, rapid footsteps. |
Stop When Follow Target Is Destroyed |
Stops followed loops when their owner disappears. | Engine loop following a vehicle. |
Use for menu selection, buttons, pause screen.
Event settings:
Event Id: ui.click
Category: Ui
Playback Mode: OneShot
Spatial Mode: TwoD
Clip Selection Mode: Random
Volume: 1
Random Pitch: 0.03
Ignore Listener Pause: true
Max Voices: 4
Cooldown Seconds: 0.02
Programmer call:
AudioManager.Instance.Play(AudioEventIds.UI_CLICK);Use for a world sound at a specific position.
Event settings:
Event Id: sfx.explosion.large
Category: Sfx
Playback Mode: OneShot
Spatial Mode: World3D
Spatial Blend: 1
Min Distance: 2
Max Distance: 80
Rolloff Mode: Logarithmic
Random Pitch: 0.05
Max Voices: 6
Voice Limit Behavior: StealOldest
Programmer call:
AudioManager.Instance.PlayAt(AudioEventIds.SFX_EXPLOSION_LARGE, explosionPosition);Use several clip variations and call from animation events or movement code.
Event settings:
Event Id: sfx.player.footstep
Category: Sfx
Playback Mode: OneShot
Spatial Mode: World3D
Clip Selection Mode: Random
Random Volume: 0.08
Random Pitch: 0.06
Min Distance: 1
Max Distance: 18
Max Voices: 4
Cooldown Seconds: 0.05
Programmer call:
AudioManager.Instance.PlayAt(AudioEventIds.SFX_PLAYER_FOOTSTEP, transform.position);Designer-only scene test:
- Add
AudioEmitterto the player. - Assign the footstep event.
- Leave
Follow Transformoff. - Call
AudioEmitter.Play()from an animation event.
Use for a sound that follows an object and keeps playing.
Event settings:
Event Id: sfx.vehicle.engine-loop
Category: Sfx
Playback Mode: Loop
Spatial Mode: World3D
Fade In Seconds: 0.2
Fade Out Seconds: 0.3
Stop When Follow Target Is Destroyed: true
Programmer call:
private AudioPlaybackHandle engineSound;
private void OnEnable()
{
engineSound = AudioManager.Instance.PlayFollow(AudioEventIds.SFX_VEHICLE_ENGINE_LOOP, transform);
}
private void OnDisable()
{
engineSound.Stop();
}Use Playback Mode: Music so starting a new music event fades out the current music voice.
Event settings:
Event Id: music.combat
Category: Music
Playback Mode: Music
Spatial Mode: TwoD
Fade In Seconds: 1
Fade Out Seconds: 1
Output Mixer Group: Music
Programmer call:
AudioManager.Instance.Play(AudioEventIds.MUSIC_COMBAT);Use an AudioZone to change ambience or mixer state when the player enters a trigger.
Steps:
- Create a GameObject named
Forest Audio Zone. - Add a
Box Collider. - Enable
Is Trigger. - Add
AudioZone. - Set
Required TagtoPlayerif your player uses that tag. - Assign an
Enter Event,Exit Event, snapshots, or mixer parameter values.
When the matching object enters the trigger, the zone applies enter audio. When the last matching object exits, it applies exit audio.
Add from:
GameObject > BitemDev > Audio Engine > Audio Manager
Purpose:
The central playback system. This should be the only object that creates and controls pooled runtime AudioSource voices.
Fields:
| Field | Purpose |
|---|---|
Config |
Optional AudioEngineConfig asset. Recommended. |
Event Library |
Library used for string/id lookup. Usually assigned from config. |
Master Mixer |
Mixer used when setting parameters without a specific mixer. |
Reference Mode |
Camera-only or separate listener/logic reference. Usually assigned by config or rig. |
Listener Transform |
Transform used as the listener reference. Usually camera. |
Logic Reference Transform |
Transform used for gameplay audio logic. Usually player. |
Initial Pool Size |
Number of pooled audio voices created at startup. |
Max Pool Size |
Hard cap for pooled voices. |
Allow Pool Growth |
Allows pool to grow from initial to max. |
Dont Destroy On Load |
Keeps the manager across scenes. |
Use Main Camera Fallback |
Uses Camera.main if no listener was assigned. |
Common programmer methods:
AudioManager.Instance.Play("ui.click");
AudioManager.Instance.PlayAt("sfx.explosion.large", position);
AudioManager.Instance.PlayFollow("sfx.vehicle.engine-loop", transform);
AudioManager.Instance.StopEvent("ambience.forest.loop");
AudioManager.Instance.StopAll();
AudioManager.Instance.SetConfiguredVolume("Master", 0.8f);Add from:
GameObject > BitemDev > Audio Engine > Audio Reference Rig
Purpose:
Connects the scene camera and logic reference to the manager.
Fields:
| Field | Purpose |
|---|---|
Reference Mode |
Chooses camera-only or dual-reference behavior. |
Listener Camera |
Camera that should hold the AudioListener. |
Logic Reference |
Player/reference transform used for gameplay audio logic. |
Ensure Audio Listener On Camera |
Adds an AudioListener to the camera if missing. |
Important:
Unity should only have one active AudioListener in a scene. If multiple cameras have listeners, disable or remove the extras.
Add manually to a scene object.
Purpose:
A small designer-friendly component that notifies AudioManager without custom code. Useful for props, animation events, timeline events, triggers, or quick tests.
Fields:
| Field | Purpose |
|---|---|
Audio Event |
Direct event asset reference. Preferred for scene objects. |
Event Id |
String id fallback if no asset is assigned. |
Play On Start |
Plays once when the object starts. |
Play On Enable |
Plays when the object is enabled after Start. |
Follow Transform |
If true, the sound follows this GameObject. Good for loops. |
Volume Scale |
Per-emitter volume multiplier. |
Pitch Scale |
Per-emitter pitch multiplier. |
Public methods:
Play()
Stop()These can be called from UnityEvents or animation events.
Purpose:
Trigger area that applies audio changes when matching objects enter or exit.
Fields:
| Field | Purpose |
|---|---|
Trigger Layers |
Which layers can activate the zone. |
Required Tag |
Optional tag filter, such as Player. |
Enter Event |
Event played when the first matching object enters. |
Exit Event |
Event played when the last matching object exits. |
Enter Snapshot |
Audio Mixer snapshot transitioned to on enter. |
Exit Snapshot |
Audio Mixer snapshot transitioned to on exit. |
Snapshot Transition Seconds |
Transition time for snapshots. |
Enter Parameters |
Mixer parameters applied on enter. |
Exit Parameters |
Mixer parameters applied on exit. |
Works with 3D colliders and 2D colliders.
Purpose:
Writes a distance-based value into an exposed Audio Mixer parameter.
This component supports gameplay-driven audio logic. It measures distance from the manager's logic reference, not necessarily the camera.
Fields:
| Field | Purpose |
|---|---|
Target |
Object being measured. If empty, uses this transform. |
Mixer |
Mixer that owns the exposed parameter. If empty, uses manager master mixer. |
Exposed Parameter |
Name of the exposed mixer parameter. |
Value Mode |
Raw value, linear volume converted to dB, or direct dB. |
Max Distance |
Distance that maps to the end of the 0-1 range. |
Invert |
If true, close = 1, far = 0. |
Update Interval |
Time between parameter updates. |
Example:
- Enemy near player = combat intensity close to
1. - Enemy far from player = combat intensity close to
0. - In
CameraOnlymode, distance is measured from the camera. - In
SeparateListenerAndLogicReferencemode, distance is measured from the assigned logic reference.
Purpose:
List of all event assets that can be played by id.
The manager uses this to resolve:
AudioManager.Instance.Play("sfx.player.jump");If an event is not in the library, string/id playback will fail and log a warning.
Purpose:
Global configuration for the manager.
Fields:
| Field | Purpose |
|---|---|
Event Library |
Main library used by the manager. |
Master Mixer |
Default mixer for parameter writes. |
Reference Mode |
Default reference mode. |
Initial Pool Size |
Startup voice count. |
Max Pool Size |
Maximum voice count. |
Allow Pool Growth |
Allows voice pool to grow when busy. |
Dont Destroy On Load |
Keeps audio manager alive across scenes. |
Use Main Camera Fallback |
Uses Camera.main if no listener is assigned. |
Volume Bindings |
Named mixer volume controls for settings menus. |
Volume binding example:
Label: Master
Mixer: MainAudioMixer
Exposed Parameter: MasterVolume
Default Linear Volume: 1
Programmer call:
AudioManager.Instance.SetConfiguredVolume("Master", 0.75f);The manager converts linear volume to decibels correctly.
Recommended usage:
using BitemDev.AudioEngine;
using BitemDev.AudioEngine.Generated;
using UnityEngine;
public sealed class ExampleAudioCaller : MonoBehaviour
{
public void Confirm()
{
AudioManager.Instance.Play(AudioEventIds.UI_CONFIRM);
}
public void Explode(Vector3 position)
{
AudioManager.Instance.PlayAt(AudioEventIds.SFX_EXPLOSION_LARGE, position);
}
}For looping sounds:
using BitemDev.AudioEngine;
using BitemDev.AudioEngine.Generated;
using UnityEngine;
public sealed class EngineAudio : MonoBehaviour
{
private AudioPlaybackHandle handle;
private void OnEnable()
{
handle = AudioManager.Instance.PlayFollow(AudioEventIds.SFX_VEHICLE_ENGINE_LOOP, transform);
}
private void OnDisable()
{
handle.Stop();
}
}Avoid this in gameplay code:
GetComponent<AudioSource>().Play();Prefer this:
AudioManager.Instance.PlayAt(AudioEventIds.SFX_PLAYER_FOOTSTEP, transform.position);The package works without an Audio Mixer, but a production project should use one.
Recommended mixer groups:
Master
Master/SFX
Master/Music
Master/Ambience
Master/Dialogue
Master/UI
Recommended exposed volume parameters:
MasterVolume
SfxVolume
MusicVolume
AmbienceVolume
DialogueVolume
UiVolume
In Unity's Audio Mixer:
- Create the groups.
- Expose each group volume parameter.
- Assign groups to
AudioEventDefinition.Output Mixer Group. - Add volume bindings in
AudioEngineConfig.
Before giving events to the programmer:
- Open
Tools > BitemDev > Audio Engine > Open Audio Engine Window. - Press
Validate Library. - Fix missing clips.
- Fix duplicate event ids.
- Generate
AudioEventIds.cs. - Enter Play Mode and use
Play Through Audio Manageron a few events.
Scene checklist:
- One active
AudioManager. - One active
AudioListener. AudioReferenceRig.Listener Cameraassigned.AudioReferenceRig.Logic Referenceassigned for dual-reference projects.AudioManager.Configassigned.AudioEngineConfig.Event Libraryassigned.
Check:
- Unity is in Play Mode.
- The scene has an
AudioManager. - The event has at least one clip.
- The clip volume and event volume are not
0. - The Audio Mixer group is not muted.
- There is one active
AudioListener.
Check:
- The event asset is in
AudioEventLibrary. - The id in code matches the event id exactly.
AudioManager.Event LibraryorAudioEngineConfig.Event Libraryis assigned.Validate Libraryhas no duplicate id warnings.
Check:
- Event
Spatial ModeisWorld3D. Spatial Blendis close to1.- The programmer is using
PlayAtorPlayFollow, not plainPlay. - The listener camera has the active
AudioListener.
Increase:
Min DistanceMax Distance- Event
Volume
Also check the assigned Audio Mixer group volume.
For projects where camera movement should not drive gameplay audio logic, set:
AudioReferenceRig.Reference Mode = SeparateListenerAndLogicReference
AudioReferenceRig.Listener Camera = Main Camera
AudioReferenceRig.Logic Reference = Player
For compact projects where camera position should drive everything, set:
AudioReferenceRig.Reference Mode = CameraOnly
Only one camera should have an active AudioListener. Remove or disable extra listeners.
When testing the package, useful feedback includes:
- Which Unity version was used.
- Whether installation from Git URL worked.
- Whether the default asset creation was clear.
- Whether creating and previewing events was clear.
- Whether field names made sense.
- Whether any setup step felt missing.
- Whether the camera/player reference modes match the desired workflow.
- What extra designer controls would save time.
Included:
- Central audio manager.
- Event assets.
- Event library.
- Runtime pooling.
- 2D and 3D playback.
- Followed loop playback.
- Music replacement with fade-out.
- Cooldowns and per-event max voices.
- Mixer parameter setting.
- Snapshot transitions.
- Camera-only and separate listener/logic reference modes.
- Designer setup window.
- Library validation.
- Generated event id constants.
Not included yet:
- Timeline clips.
- FMOD/Wwise integration.
- Custom waveform preview.
- Import preset automation for audio files.
- Save-file persistence for user volume settings.