Overview
The AudioSystem has three layers. AudioCommandFactory builds commands. AudioFlowController receives commands from the bus and passes them on. AudioManager and its helper classes do the work.
Main manager and coordinator classes
AudioManager
The central MonoBehaviour. A project subclass provides the language, volume preset, button handling, and apply-button handling.
Responsibilities:
- Holds the singleton
Instance, and keeps itself across scene loads. - Creates the
AudioSourcePoolandAudioClipLookupinAwake. - Routes incoming audio commands to playback, pause, stop, volume, and layered music methods.
- Tracks music playback in
AudioStaterecords. - Applies volume presets through
AudioMixerManager. - Forwards layered music calls to an
ILayeredMusicPlayer. - Handles UI-domain events from
ProcessEvent.
Serialized fields to set in the Inspector: AudioMixer, AudiosHolder, MusicHolder, LocalizedGroupAudiosHolder, PooledObjectsAudio, and PooledObjectsMusic.
Subclass requirements: GetCurrentLanguage, GetVolumePreset, HandleButtonClicked, and HandleApplyButtonClicked.
Setup order: SetAudioTweener and SetLayeredMusicPlayer are called by the project. Awake runs before those calls, so the pool and lookup exist when the first command arrives.
AudioFlowController
The bridge between the buses and AudioManager. A project subclass implements HandleCommand, typically by calling AudioManager.HandleCommand. The base class handles the Audio domain registration in FlowController.Init and the UI event subscription in its own Init.
It is registered through InitializationManager.RegisterSystems, using SafeRegister.
AudioMixerManager
A MonoBehaviour that wraps the Unity AudioMixer. It should be a child of the AudioManager GameObject. It exposes setters and getters for the Master, Music, and SFX parameters, in decibels.
AudioSourcePool
A plain class used by AudioManager. It creates pooled sources in its constructor, under the given parent transform. It does not decide when to play or stop; AudioManager makes those decisions.
AudioClipLookup
A plain class used by AudioManager. It builds the clip key lookup from the holder lists and resolves clips by key and language. It does not play audio.
AudioCommandFactory
A static class used by game code. It builds Audio-domain commands and sends them with BusUtility.Send. It does not hold any state.
Key event and data classes
AudioState: one record per tracked music clip. Created and updated byAudioManager. Read withGetAudioState.VolumeMix: a set of SFX, Music, and Master values. Passed through commands and presets.AudioConstants.AudioClipData: the per-clip settings: key, clip, volume, pitch, priority, loop, play on awake, and mixer group.AudioClipHolder,LocalizedGroupAudioClipHolder,NonLocalizedGroupAudioClipHolder: ScriptableObjects that store clip data for lookup.LocalizedAudioSlideGroup,LocalizedAudioVariant,AudioClipSubGroup: serializable data types that the holders use.AudioParamKeysandContractConstantsAudio: typed keys and string tokens for command parameters.AudioCommandVerb,AudioScope,AudioSubject: enums that describe a command.
Commands do not carry events. Audio notifications from the playback layer, such as the clip-finished callback, are passed as Action<AudioClip> values. Those are stored in command parameters or passed as method arguments.
Handler and listener interfaces
IAudioTweener: fading contract. Implemented by the project.ILayeredMusicPlayer: layered music backend contract. Implemented by the project.ILayeredMusicDataStore: progress persistence contract. Implemented by the project.IEventReceiver: implemented byAudioFlowController, so the initialization registry classifies it as an event receiver. The receiver is initialized before other sync systems.ICommand: the command typeAudioManager.HandleCommandaccepts. It is defined outside this folder.
Interaction with dependency classes
AudioCommandFactoryusesCommand.Create,BusUtility.Send, andCoreParamKeys.ObjectValue.BusUtility.Sendplaces the command on theCommandBus.AudioFlowControllergets the buses fromServiceLocator.GetBusRegistry, throughFlowControllerand its ownInit. It registers for the Audio domain through the base class and for UI events through theEventBus.FlowControlleris the base class forAudioFlowController. ItsInitregisters the controller on theCommandBus.InitializationManagercreates the buses and runsIniton each registered system.AudioFlowControllerruns as an event receiver during the sync phase.ParamKey<T>andParamscarry typed values.AudioManagerreads them withHas,Get, andTryGet.
Flow examples
Playing a sound effect with a callback:
- Game code calls
AudioCommandFactory.PlayClipWithCallbackwith a clip key and a callback. - The factory sends a Play command for the SFX subject, with the clip key and callback.
AudioFlowControllerpasses the command toAudioManager.HandleCommand.AudioManagercallsPlayClip, thenPlayAudio. It resolves the clip for the current language, gets a pooled source, and callsAudioPlaybackUtility.Play.- When a non-looping clip ends, the callback runs with the clip, and the source is deactivated.
Restoring layered music:
- Game code calls
AudioCommandFactory.RestoreMusicProgress. AudioManagercallsRestoreMusicProgress, which callsLayeredMusicPlayer.RestoreProgress.- The player reads progress from its data store, applies it, and starts playback.
Changing the volume preset:
- Game code calls
AudioCommandFactory.SetVolumewith a context, source, channel, and preset. AudioManagersets the context, then callsApplyVolumePreset.- If the source is
Saved, the values come fromGetVolumePreset. The mixer then receives the values for the selected channel throughAudioMixerManager.
UI button events:
- The event bus delivers a UI event to
AudioFlowController.OnEvent. AudioManager.ProcessEventpasses it to the UI handler.- For a button click,
HandleButtonClickedruns. The project implements it.