Music System¶
The Music System (CrawlerKitMusic module) handles background music across all scenes. A single MusicManager lives in the Main Menu scene and persists through every scene transition via DontDestroyOnLoad. It crossfades between states using dual AudioSources (A/B swap) and automatically switches to Combat music when enemies enter the party's range.
Music states¶
| State | When it plays |
|---|---|
None |
Silence — no track playing |
Menu |
Main menu scene |
Exploration |
Dungeon levels, no enemies nearby |
Combat |
At least one enemy is within Combat Radius cells of the party |
Combat detection is proximity-based — the manager polls every second and checks whether any alive enemy is within a configurable number of grid cells. Enemies in other rooms don't trigger combat music. When no enemies remain nearby, the system waits a configurable delay before returning to Exploration.
Setup¶
1. Create MusicStateData assets¶
For each state you want music in, create a MusicStateData asset:
Assets → Create → Dungeon Crawler Framework → Music State Data
Configure each asset in the Inspector:
| Field | Description |
|---|---|
| Tracks | Audio clips to play. Add as many as you want. |
| Play Order | Random — picks a clip at random (avoids repeating the same one twice in a row). Sequential — plays in order, wrapping back to the first. |
| Loop Track | If enabled, the current clip loops until the state changes. If disabled, automatically advances to the next clip when it ends. |
| Volume | Target volume for this state (0–1). Multiplied by the manager's master volume. |
| Fade In Time | Seconds to fade in when entering this state. |
| Fade Out Time | Seconds to fade out when leaving this state. |
2. Add MusicManager to the Main Menu scene¶
Create an empty GameObject in your Main Menu scene and add the Music Manager component (Dungeon Crawler Framework → Music Manager).
Assign your MusicStateData assets:
| Slot | Asset to assign |
|---|---|
| Menu Music | Your menu MusicStateData |
| Exploration Music | Your dungeon ambient MusicStateData |
| Combat Music | Your combat MusicStateData |
Inspector settings:
| Field | Description |
|---|---|
| Master Volume | Global volume multiplier (0–1). All state volumes are multiplied by this. |
| Auto Combat Detection | When enabled, automatically switches to Combat when an enemy enters range and back to Exploration when the area is clear. |
| Combat Radius | Distance in grid cells within which an enemy triggers combat music. Enemies further away are ignored. Default: 6. |
| Detection Interval | How often (in seconds) the manager checks for nearby enemies. Default: 1s. |
| Combat Exit Delay | Seconds to wait after no nearby enemies remain before switching back to Exploration. Prevents music cutting in and out. |
| Debug Log | Logs every state change and detection tick to the Console. Useful during development. |
One MusicManager per project
Only place the Music Manager in the Main Menu scene. If the menu scene is loaded again (e.g. "Return to menu"), the duplicate is destroyed automatically. Do not add it to every dungeon scene.
3. Add SceneMusicSetup to every other scene¶
Add a Scene Music Setup component (Dungeon Crawler Framework → Scene Music Setup) to any GameObject in each scene (e.g. a _GameManager object). Set the State field to whatever music should play in that scene.
| Field | Description |
|---|---|
| State | Music state to activate when this scene loads. |
| Immediate | Skip the crossfade — cut to the new track instantly on scene load. |
Common setups:
| Scene type | State |
|---|---|
| Main Menu | (MusicManager auto-starts menu music on its own — no SceneMusicSetup needed) |
| Dungeon level | Exploration |
| Boss arena | Combat |
| Cinematic / cutscene | None |
Controlling music from code¶
Access the system through the service locator:
Switch state:
music.SetState(MusicState.Combat);
music.SetState(MusicState.Exploration, immediate: true); // no fade
Stop all music:
Adjust master volume at runtime:
Read current state:
How crossfading works¶
The manager keeps two AudioSource components (MusicSource_A and MusicSource_B). When a state change occurs:
- The outgoing source fades to volume 0 over
fadeOutTimeseconds. - The incoming source starts at volume 0 and fades up to the target volume over
fadeInTimeseconds. - Both happen simultaneously — the two fade times are independent.
- Once the fade completes, the outgoing source is stopped and the roles swap for the next transition.
This means a transition from Exploration to Combat uses the Combat state's fade times, and the transition back uses Exploration's fade times.
Architecture¶
CrawlerKitMusic/
└── Runtime/
├── IMusicSystem.cs # Interface + MusicState enum
├── MusicStateData.cs # ScriptableObject — audio clips + settings per state
├── MusicManager.cs # Persistent MonoBehaviour — crossfade, combat detection
└── SceneMusicSetup.cs # Per-scene component — declares the base music state
The MusicManager registers itself as IMusicSystem in CrawlerServices during Awake, so any other module can reach it without a direct reference. It also re-binds to IEnemyManager on every scene load, so combat detection works correctly after scene transitions where the enemy manager is recreated.