🏠 1. Introduction

Advanced Audio Dispatcher for DOTS is a high-performance, thread-safe, and zero-GC bridge between Unity's Data-Oriented Technology Stack (DOTS) and the native FMOD Studio C-API.

Built specifically for Entities 1.0+ and the Burst Compiler, this asset allows you to dispatch thousands of audio events directly from your IJobEntity systems without allocating a single byte of managed memory.

Key Features:

Why this asset?

The official FMOD Unity integration is fantastic for traditional OOP projects, but it relies heavily on MonoBehaviour, managed strings, and Main Thread execution. Using it in a DOTS project forces you to break the ECS paradigm, leading to thread locks and garbage collection spikes.

Audio Dispatcher solves this by bypassing the official C# wrapper entirely. It communicates directly with the raw FMOD native binaries (fmodstudioL.dll), providing a pure ECS architecture designed for AA/AAA performance.


⚙️ 2. Getting Started

Installation

🛑 CRITICAL WARNING: Do NOT import the full official FMOD Unity package into your DOTS project. It will clutter your project with unnecessary MonoBehaviours and cause compilation conflicts.

Step 1: Get the Native Libraries

  1. Download the official FMOD for Unity package from fmod.com.
  2. Import the .unitypackage into your Unity project.
  3. In the Import Window, click "None", and ONLY check the Plugins folder. Uncheck Scripts, Editor, and everything else.

Step 2: Install Audio Dispatcher

  1. Open Window -> Package Manager.
  2. Click the + icon and select Add package from tarball...
  3. Select the com.snivelercode.audio-dispatcher.fmod-1.0.0.tgz file.

Project Settings

Once installed, navigate to Edit -> Project Settings -> SnivelerCode.
Here you can configure the core behavior of the audio engine:

Bank Synchronization

  1. Build your FMOD Studio project and export the .bank and .strings.bank files.
  2. Drag and drop them anywhere into your Unity project.
  3. Create an empty GameObject in your SubScene and attach the Fmod Sounds Library Authoring component.
  4. The system will automatically detect your banks, copy them to StreamingAssets, and generate safe, stringless ulong IDs for all your events, buses, and parameters.

💻 3. Core API

To play sounds from a Burst-compiled job, you need to pass the FmodRuntimeAudio.ParallelWriter to your job.

Playing One-Shots

One-shots are "fire-and-forget" sounds (e.g., footsteps, gunshots, impacts). If the sound is spawned outside its audible range (defined in FMOD Studio), it is instantly culled to save CPU.

[BurstCompile]
public partial struct WeaponFireJob : IJobEntity
{
    public SncRuntimeAudio.ParallelWriter AudioWriter;

    private void Execute(in LocalTransform transform, in FireEvent fireEvent)
    {
        // Plays a sound at the given position with 80% volume
        SncAudioID.WeaponsGunshot.Shot(transform.Position)
            .Volume(0.8f)
            .Pitch(1.1f)
            .Apply(AudioWriter);
    }
}

Looping Sounds & Lifecycle

When you call .Loop(entity), the system creates a lightweight Shadow Entity. This entity automatically tracks your target's position, rotation, and velocity (for the Doppler effect).

💡 Info: You do not need to stop loops manually! If you destroy the target entity (e.g., the enemy dies), the Shadow Entity detects it, tells FMOD to smoothly fade out the sound, and destroys itself. Zero memory leaks.

// Start a looping engine sound attached to a vehicle entity
SncAudioID.VehiclesEngine.Loop(entity)
    .Volume(1.0f)
    .Apply(AudioWriter);

Dynamic Parameters & Properties

You can change FMOD Local Parameters or built-in properties (like Min/Max 3D Distance) on the fly for any active loop.

// Update the RPM parameter of an already playing engine loop
SncAudioID.VehiclesEngine.Change(entity)
    .Param(SncAudioParamID.VehiclesEngine.RPM, 3500f)
    .Apply(AudioWriter);

Global Commands

Control buses and global parameters without string allocations. IDs are automatically generated from your .strings.bank.

// Pause the SFX bus (e.g., when the game is paused)
AudioWriter.SetBusPaused(SncBusID.GameSfx, true);

// Change Music Volume
AudioWriter.SetBusVolume(SncBusID.Music, 0.5f);

// Update a Global Parameter
AudioWriter.SetGlobalParameter(SncGlobalParamID.TimeOfDay, 14.5f);

🎭 4. Hybrid ECS & Animation

The FmodAnimatorBridge

Syncing standard Unity Animations (like footsteps) with DOTS audio is usually a headache. We solved this with the component.

  1. Attach SncAnimatorBridge to your character GameObject (next to the Animator).
  2. Add a new element to the Audio Events array.
  3. Give it a name (e.g., Footstep) and select your sound from the beautiful [SncEvent] dropdown.
  4. Open the Unity Animation Window, add an Animation Event, select PlayAudioEvent(string), and type Footstep.

The bridge will safely catch the OOP event and dispatch it to the Burst-compiled DOTS queue without any GC allocations!

Proxy API

If you need to play a sound from a standard MonoBehaviour (e.g., a UI Button click), use the Proxy API extensions:

public void OnButtonClick()
{
    SncAudioID.UI_Click.Shot(transform.position).ProxyEvent();
    SncBusID.Master.ProxyBusVolume(0.5f);
}

🧱 5. Advanced Features

Asynchronous Raycast Occlusion

The package includes a highly optimized, multi-threaded occlusion system. It uses Unity's RaycastCommand to check for obstacles between the listener and the sound source.

Smart Culling & Virtualization

Audio Dispatcher uses FMOD Studio as the Single Source of Truth.
It automatically reads the MaxDistance of your events from the FMOD banks.


🐞 6. Debugging & Profiling

Visual Debugger

To help you profile your audio, we included a high-performance Visual Debugger.

  1. Go to Edit -> Project Settings -> SnivelerCode.
  2. Enable Visual Debugger.
  3. Open the Scene View while in Play Mode.

You will see wireframe spheres representing the Min/Max distance of your sounds, color-coded icons showing their playback state (Playing, Stopped, Virtualized), and real-time occlusion percentages.


❓ 7. FAQ & Troubleshooting

Q: I get a DllNotFoundException: fmodstudioL error.
A: You forgot to import the native libraries. Download the official FMOD for Unity package and import only the Plugins folder into your project.

Q: My background music is being culled/muted when I move the camera!
A: Your music event is being treated as a 3D sound. Open FMOD Studio, select your music event, and delete the Spatializer effect from the Master Track. Rebuild your banks. The system will automatically detect it as a 2D sound (MaxDistance = 0) and disable culling for it.

Q: When I spawn 1,000 enemies, some sounds don't play or cut off abruptly.
A: You are experiencing "Voice Stealing Thrashing". FMOD has a hard limit of 256 channels.

  1. Open FMOD Studio and reduce the Max Distance of your enemy sounds so they cull earlier.
  2. Set Max Instances (e.g., to 20) in the event's Macros, and set Stealing to Virtualize or Furthest.
  3. Ensure your looping sounds have a Loop Region on the FMOD timeline, otherwise, they will die naturally while virtualized.

Edit on GitHub v1.0.0