Music Transition Designer A state-driven adaptive music system for Unity
This guide covers everything you need to set up, author, and control adaptive music with Music Transition Designer (MTD), from first import through to runtime scripting.
com.unity.addressables) for SoundBank loading.1 — Import & First-Time Setup
Import the MusicTransitionDesigner Unity package. MTD will install to Assets/MusicTransitionDesigner and create default asset folders. Once imported, the Startup Window will open automatically.
Create Core Data Assets
In the Startup Window, click the button to generate the core data assets. This creates two ScriptableObjects:
- MtdProjectSettings — defines both runtime and editor behaviour (mixer groups, fade durations, debugging, default asset paths, and more).
- MtdEditorData — editor-only data that stores folder organisation and file ordering for the Asset Manager. Deleting this file will reset the Asset Manager, removing all folders and custom ordering.
2 — Configure Project Settings
Navigate to to configure:
Audio Configuration
- BGM Mixer Channel
- AudioMixer group for background music playback.
- Stinger Mixer Channel
- AudioMixer group for stinger playback.
- Stinger Pool Size
- How many stinger
AudioSourceinstances are created when you generate a new Audio Source Pool prefab. The default is 8. - User Latency Offset (ms)
- Global latency compensation for bar/beat callbacks. Internal compensation is already applied; this defaults to 0.
Initialisation
- Persistent Banks
- SoundBanks loaded automatically when the MusicSystem initialises, remaining loaded for the entire session. These are in addition to scene-specific banks. Persistent banks are protected from external unloading.
Global Fade Timings
- Pause Fade Duration (ms)
- Default fade time for pause, resume, and stop operations when
-1is passed as the fade parameter via the API or components.
Debugging
- Periodic Status Log
- Generates a periodic console log detailing the current system state (enabled/disabled/paused/playing, active track, game states, loaded banks, etc.).
- Log Interval (ms)
- Interval between status logs (default 10000).
- Enable Logging
- Master toggle for all MTD console logging.
- Global Verbosity
-
WarningsOnly — only warnings and errors.
Basic — standard operational messages.
Detailed — verbose debugging output.
Metronome
- Beat 1 / Other Beats
- Audio clips used by the in-editor metronome preview. Defaults are provided with the package.
Default Asset Paths
If folders are moved or renamed, update the paths here manually to ensure the Asset Manager Open/Save explorers default to the correct folder.
3 — Import Audio Files
Import your audio clips to the 00_AudioFiles folder (or your configured default). Audio clips used by MTD must be marked as Addressable in Unity's Addressables system before they can be assigned to Music Tracks.
4 — The Asset Manager
Open the Asset Manager via .
The Asset Manager is the centralised hub for creating, organising, editing, and validating every MTD asset type. It provides a tabbed interface with sections for:
| Asset Type | Purpose |
|---|---|
| Music Tracks | Define a track's metadata (BPM, time signature, markers, entry/exit points). |
| State Groups | Define game-state categories and their possible values. |
| State Trees | Map state combinations to State Outcomes. |
| State Outcomes | Control which Music Track plays and how (start/stop positions, loop behaviour). |
| Outcome Categories | Tag State Outcomes for use in grouped Transition Rules. |
| Transition Rules | Define sync, timing, and fade behaviour between State Outcomes. |
| SoundBanks | Package assets together for runtime loading. |
Each section has options to create, move, and delete assets and folders. Nested folders are supported. Folder organisation is purely for the Asset Manager's display and is stored in the MtdEditorData asset.
Recommended Creation Order
Assets build upon each other, so they are best created in this order:
- Music Tracks
- State Groups
- State Trees (State Outcomes can be created directly from within the State Tree editor)
- State Outcomes (edit any generated from the State Tree)
- Transition Rules
- SoundBanks
5 — Music Tracks
A Music Track is a ScriptableObject that wraps an audio clip with musical metadata, providing timing context to the playback system and facilitating synchronised callbacks. From the Asset Manager, double-click a Music Track in the list to open the Music Track Editor.
Track Properties
- Audio Clip
- An Addressable reference to an AudioClip. The clip must be marked as Addressable.
- Track Name
- Display name used for debugging purposes only.
- Volume (dB)
- Default volume adjustment in dBFS. This is used unless overridden by a State Outcome. Range: −80 dB (silent) to 0 dB (full volume).
- BPM
- Tempo in beats per minute.
- Beats Per Bar
- Time signature numerator (e.g. 4 for 4/4 time).
- Beat Value
- The note value that represents a beat: Eighth (1/8), Quarter (1/4), Dotted Quarter, or Half (1/2).
- Allow Beat Subscription
- If enabled, this track can provide beat/bar callbacks to API subscribers. Disable for non-rhythmic tracks or tracks with tempo variation.
Entry & Exit Points
Bar 1, Beat 1 is anchored to the Entry Point. All musical time values are relative to it.
- Entry Point (ms)
- The default start position, in milliseconds from the beginning of the audio file. This is where Bar 1, Beat 1 sits.
- Exit Point
- When the track will stop or loop (depending on State Outcome settings). Specified in Bars/Beats/Ms.
- Lead-In Duration
- Optional. A pre-roll section before the Entry Point. If a State Outcome or Transition Rule utilises the lead-in, playback begins earlier so that the Entry Point aligns with the transition Sync Point. Specified in Bars/Beats/Ms.
- Tail Duration
- Optional. A section after the Exit Point. If the track reaches its Exit Point, the tail plays. If a State Outcome is set to loop, the tail plays across the loop. Specified in Bars/Beats/Ms.
Timings for Lead-In, Exit Point, Tail, and Markers can be set either:
- From the playhead marker on the waveform display, or
- To the start or end of the audio file, or
- Manually by inputting the musical time (Bars/Beats/Ms) and pressing Set. The Ms field is a fine-tuning offset and can accept negative values.
Track Markers
Markers are named positions on the track timeline that can be referenced by State Outcomes and Transition Rules as Sync Points, Playback Start Positions, Loop To Positions, and Play Until Positions. Each marker has a unique internal GUID for stable referencing.
Deleting a Track Marker will automatically null any references to it by State Outcomes and Transition Rules (but not by components). Likewise, re-ordering markers may break playback logic (e.g. by causing a State Outcome's Playback Start Position to be later than its Play Until position). In both cases, dependent assets will be marked invalid until the issue is fixed.
Preview Settings
Set start, stop, and loop behaviour for the Music Track's playback preview. These settings are editor-only and are not used at runtime.
Waveform Display
- Draw fades by dragging the white handles. Right-click to select the fade shape (Linear, Logarithmic, Exponential, S-Curve, Square Root).
- The Playhead and Track Markers can be dragged and will snap to the grid. Hold Shift to fine-tune the drag.
- Click anywhere on the waveform to position the playhead. Double-click the playhead for quick playback from that point.
6 — State Groups
MTD uses state evaluation to trigger music automatically at runtime. A State Group represents a game-state category (e.g. "Location", "CombatStatus") and contains a list of possible State values (e.g. "Area1", "Area2", "InCombat", "OutOfCombat"). Open a State Group from the Asset Manager by double-clicking it in the list.
Properties
- Group Name
- A mandatory, unique identifier for this State Group.
- States
- A list of named state values. Each state has a unique internal GUID.
- Is Enabled
- Whether the State Group is active and can be registered.
Identification
State Groups can be referenced in three ways:
- Direct asset reference (most robust).
- By Group Name (string; less stable if renamed).
- By Asset GUID (stable; survives renaming).
Individual states within a group can be referenced by State Name or State GUID. The API accepts any combination of these identifiers. Press Copy ID to copy a State's GUID to the clipboard.
Validation
- Group Names must be unique across all State Groups in the project.
- State names must be unique within an individual State Group.
- At least one state must be defined.
When finished, always press Validate and Enable first, then Save. If there are any issues, the asset will not validate until they are resolved.
7 — State Trees
A State Tree maps combinations of game states (from State Groups) to State Outcomes. When conditions are met for a branch, that branch's State Outcome triggers, telling the playback system which Music Track to play and how. Open a State Tree from the Asset Manager by double-clicking it in the list.
Building a State Tree
- Add State Groups to the State Hierarchy. These form the columns of the decision matrix.
- Press New Path to create a condition branch.
-
Press the foldout arrow to reveal the branch's state columns, then select which state combinations must be met for the branch to evaluate as true.
- States within a column are evaluated as OR (any can be true).
- Multiple columns are evaluated as AND (all must be true).
- Create or select the State Outcome that will play if the branch's conditions are met. Leave the State Outcome field null for silence.
Evaluation & Shadowing
Evaluation takes place top to bottom. The first matching entry wins. If any branch shadows (makes it impossible to reach) a lower branch due to duplicate conditions, the shadowed branch will display a warning icon.
- Press the Check Shadowing button to display only shadowed paths.
- Hover over the warning icon to see information (limited to one issue at a time).
The editor detects three types of issues:
- Shadowed — entries completely covered by a higher-priority entry.
- Partially blocked — entries with some unreachable routes.
- Duplicates — entries with identical logic to another entry.
Folders
Entries can be organised into folders within the State Tree editor for readability. Folder structure does not affect evaluation order; only the flattened priority order matters.
Runtime
Only one State Tree may be active at any one time. Switching trees at runtime will trigger a State Evaluation.
8 — Outcome Categories
Transition Rules define how one track transitions to another. Transitions can target specific State Outcomes, entire Outcome Categories, Any, or None. While State Outcomes are highly specific and Any serves as a wildcard, Outcome Categories provide a middle ground.
Rather than creating multiple Transition Rules with identical transition behaviour, you can assign Outcome Category tags to State Outcomes that share identical transition requirements, then create Transition Rules for the entire category.
Example
If you want all Exploration tracks to transition into all Combat tracks in the same way, instead of creating a separate Transition Rule for every State Outcome pair, you could create a single Exploration → Combat rule. If time signature is a relevant factor, you could create categories like Exploration4-4 and Combat3-4.
Outcome Category assets serve purely as tags. The asset itself is the identifier and holds no properties beyond Is Enabled.
Create Outcome Categories in the State Outcomes tab of the Asset Manager.
When finished editing an Outcome Category, press Validate and Enable, then Save.
9 — State Outcomes
A State Tree tells the playback system which State Outcome should trigger when a branch's conditions are met. A State Outcome tells the playback system which Music Track to play and how. Open a State Outcome from the Asset Manager by double-clicking it in the list.
Properties
- Music Track
- The Music Track to play when this outcome is triggered.
- Category
- Optional. Assign this State Outcome to an Outcome Category for use in grouped Transition Rules.
- Is Enabled
- Whether this outcome is active.
Playback Settings
- Play From
-
Entry Point — the track's default entry position.
Marker — a specific named marker.
Random Marker — a randomly chosen marker from a selection. - Play Lead-In
- Whether to include the track's lead-in section.
- Play Until
-
Exit Point — the track's defined exit position.
Marker — a specific named marker. - Loop
- Whether to repeat when reaching the Play Until position.
- Loop To
-
Entry Point — the track's entry.
Marker — a specific marker. - Play Tail On Exit
- Whether to play the tail section when reaching the exit point, either during looping or when finishing.
Volume Override
- Use Volume Override
- If enabled, overrides the Music Track's default volume.
- Volume Override (dB)
- The override volume level.
Validation
State Outcomes require a Music Track reference and a coherent playback timeline to validate: the Play Until position must be later than the Play From and Loop To positions. Ineligible markers are hidden from the menu.
When finished, always press Validate and Enable first, then Save.
10 — Transition Rules
Transition Rules define how one Music Track should transition to another when a new State Outcome is triggered. They control synchronisation, timing, fade behaviour, and optional overlays. Open a Transition Rule from the Asset Manager by double-clicking it in the list.
Rule Definition
Each rule defines a transition path between Track A (source/outgoing) and Track B (destination/incoming):
- Direction
- One Way (A→B) or Bidirectional (A↔B). Bidirectional rules are two-in-one: the same transition behaviour applies in both directions.
- Track A/B Type
-
How to match the source/destination:
StateOutcome — a specific State Outcome.
OutcomeCategory — any outcome in a given category.
Any — matches any outcome (wildcard).
None — matches when no music is playing.
Sync Point
The Sync Point is the point in time at which the incoming track will begin playing (before accounting for Lead-In or Fade/Positional offsets).
| Sync Type | Description |
|---|---|
| Immediate | Fires instantly. |
| On Next Beat | Waits for the next beat boundary. |
| On Beats Of Bar | Waits for specific beat(s) within the bar (e.g. beats 1 and 3). Wraps to the next bar if all specified beats have passed. |
| On Next Bar | Waits for the next bar boundary. |
| On Marker | Waits for a specific marker on Track A. |
| On State Outcome End | Waits for the current outcome to reach its Play Until position. |
| After X Full Bars | Counts X full bars from the start of the next bar. For example, triggering on Bar 2 Beat 2 with "After 2 Bars" results in a transition on Bar 5. |
| After X Full Beats | Counts X full beats from the start of the next beat. |
| After X Ms | Waits X milliseconds. |
Playback Start Position
Controls where the incoming track begins playing:
| Option | Description |
|---|---|
| Get From State Outcome | Uses the incoming State Outcome's default Play From setting (which may be a Track Marker). |
| From Entry Point | The track's entry position. |
| From Marker | A specific marker on Track B (one-way rules only). |
| From Random Marker | A randomly chosen marker on Track B (one-way rules only). |
| Sync Real Time | Plays the incoming track from the outgoing track's current position in real time (ms from Entry Point). |
| Sync Musical Time | Plays the incoming track from the outgoing track's current musical time (bar, beat, ms). Useful for transitioning between tracks with different BPMs; inconsistent time signatures may cause issues. |
- Use Last Played Position
- If checked, and the State Outcome has been played before, playback resumes from where it left off. Otherwise it starts from the Playback Start Position.
- Minimum Play Duration
- Optional. Prevents any other transitions from firing until the cooldown period is over. Requested transitions will be queued until then.
Transition Reversal
A Transition Reversal can occur when a transition back to the outgoing track is requested during an active transition to the incoming track (e.g. Track A is requested while already transitioning from A to B). If permitted, the system reverses the crossfade back to the outgoing track.
- Allow Transition Reversal
- Enable or disable reversal for this rule.
- Reversal Phase Flags
- Control which transition phases allow reversal: During Fade Out, During Silence, During Fade In, During Overlay.
- Reversal Fade
- Fade type and duration for the reverse transition.
Track Behaviour (Fades & Offsets)
Use the popups to specify fade and position settings for the outgoing track, incoming track, and overlay.
- Fade Settings
- Duration, offset, and curve for fading out Track A and fading in Track B. Types: Linear, Logarithmic, Exponential, S-Curve, Square Root.
- Timing Base
- Specifies which track's time signature and BPM are used to calculate bar/beat lengths. Defaults to the outgoing track for positional offsets, and to itself for fade durations. Useful for fine-tuning alignment between tracks with different BPMs.
- Positional Offsets
- Move the scheduled start time of the track without adjusting the Playback Start Position (i.e. the Playback Start Position becomes unaligned with the Sync Point).
- Fade Offsets
- Move the scheduled start time and adjust the Playback Start Position to compensate, maintaining alignment with the Sync Point.
Overlay
An Overlay is an optional additional Music Track that plays across a transition, serving as a stinger or bridge between the outgoing and incoming tracks.
- Overlay Track
- The Music Track to overlay.
- Play Lead-In / Tail
- Whether to include the overlay's lead-in and tail sections.
- Overlay Cooldown (ms)
- Time restriction on how soon the overlay can fire again.
- Volume Override
- Override the overlay track's default volume.
- Position Offset
- Offset the overlay's start position.
- Fade In / Fade Out
- Independent fade settings for the overlay.
- Align to Overlay Exit
- For the incoming track: applies an automatic position offset, aligning the Playback Start Position to the overlay's Exit Position.
Transition Rule Priority
When a transition is needed, the system searches for the best matching rule. The destination is prioritised over the source: a rule with a specific destination is preferred over one with "Any", even if the source match is less specific.
| Priority | Current | Incoming |
|---|---|---|
| 1 | StateOutcome | StateOutcome |
| 2 | OutcomeCategory | StateOutcome |
| 3 | Any | StateOutcome |
| 4 | None | StateOutcome |
| 5 | StateOutcome | OutcomeCategory |
| 6 | OutcomeCategory | OutcomeCategory |
| 7 | Any | OutcomeCategory |
| 8 | None | OutcomeCategory |
| 9 | StateOutcome | Any |
| 10 | OutcomeCategory | Any |
| 11 | Any | Any |
| 12 | None | Any |
| 13 | StateOutcome | None |
| 14 | OutcomeCategory | None |
| 15 | Any | None |
If no matching rule is found, an automatic Fallback rule is used which performs an immediate crossfade with near-zero fade duration.
When finished editing a Transition Rule, press Validate and Enable, then Save. If validation fails, fix the reported issues and try again.
11 — Sound Banks
Sound Banks package all runtime assets (tracks, outcomes, rules) for loading and unloading as a group. Audio clips are loaded via Unity Addressables when a bank is loaded, and released when unloaded. Open a Sound Bank from the Asset Manager by double-clicking it in the list.
Authoring
- Source State Trees
- The primary content source. Adding a State Tree automatically includes all its referenced State Outcomes and Music Tracks.
- Source Music Tracks
- Manually added tracks not referenced by State Trees (e.g. stingers).
- Source Transition Rules
- Manually added Transition Rules for cases not covered by auto-compilation (e.g. transitions between tracks in different Sound Banks).
Rule Compilation Mode
- Strict (recommended)
- Only includes Transition Rules where both Track A and Track B are present in this Sound Bank.
- Loose (not recommended)
- Includes rules where either Track A or Track B is present. This can include unnecessary rules and is less efficient.
Compiled Data
The editor compiles the final runtime lists:
- Compiled Tracks — all Music Tracks needed at runtime.
- Compiled State Outcomes — all State Outcomes.
- Compiled Transition Rules — all applicable rules.
Runtime Behaviour
- Multiple Sound Banks can be loaded simultaneously.
- If a Music Track appears in multiple loaded banks, the audio clip is loaded only once. A reference counter ensures the clip remains in memory until all banks containing it are unloaded.
- Loading a bank registers its outcomes and rules with the runtime asset registry.
- Unloading a bank removes its registrations and releases audio clips.
Validation
- All source assets must be valid and enabled.
- If compilation skipped any invalid/disabled assets, the bank is marked "Incomplete".
12 — Preview Window
The Preview Window lets you test your assets and transition behaviour entirely inside the editor.
Open the window
Go to .
Workflow
- Add the SoundBanks you want to test. Loading them prepares all referenced assets for preview.
- Set the active State Tree and choose the starting states.
- Press Play to start preview playback.
- Change states/trees and click Transition Now to audition the transition immediately.
- Use Save Session / Load Session to store and reopen preview setups.
13 — Scene Setup
Add the MtdSceneInitialiser prefab in every scene that uses music. This component is responsible for:
- Creating the persistent MusicSystem singleton (if one doesn't already exist).
- Loading scene-specific Sound Banks.
- Setting the initial State Tree.
- Setting initial state values.
- Optionally starting music playback automatically.
The MtdSceneInitialiser has an early execution order (−40) to ensure the music system is ready before other components try to use it.
Properties
- Persistent Scene Banks
- Sound Banks for this scene. Loaded on
Start, unloaded automatically when the scene is destroyed. Protected from external unloading via the API or MtdSoundBankControl. - Initial State Tree
- The State Tree to activate for this scene.
- Initial States
- A list of StateGroup + State pairs to set immediately on scene start.
- Playback
- Automatic playback behaviour on scene start.
Audio Source Pool Prefab
MtdSceneInitialiser requires a reference to an Audio Source Pool prefab.
- This prefab contains the
MusicChannels,OverlayAudioSources, andStingerAudioSourcesobjects. Runtime pools/channels are built from this prefab. - The package ships with a default pool prefab that provides 8 stinger channels.
Changing stinger channel count when creating new prefabs
To generate a pool prefab with a different number of stinger channels:
- Open and change Stinger Pool Size.
- Create a new pool prefab via .
- Assign the newly created prefab to the Audio Source Pool Prefab field on the first
MtdSceneInitialiserthat initialises music.
14 — Trigger System
The trigger system provides a code-free way to control music from the scene. It uses two types of components that work together: Triggers (event sources) and Actions (what happens when a trigger fires).
Triggers (Event Sources)
Triggers fire when a specific Unity event occurs. Each trigger holds a list of Actions to execute.
| Component |
|---|
MtdOnStart |
MtdOnEnable |
MtdOnDisable |
MtdOnDestroy |
MtdOnTriggerEnter |
MtdOnTriggerExit |
MtdOnTriggerStay |
MtdOnCollisionEnter |
MtdOnCollisionExit |
MtdOnBecameVisible |
MtdOnBecameInvisible |
Collision and trigger-based triggers support a Required Tags filter. If tags are specified, the trigger only fires if the colliding object matches one of the listed tags.
- Use Cooldown
- Prevents rapid re-triggering.
- Cooldown Duration (ms)
- Minimum time between fires.
Actions
Actions define what happens when a trigger fires. Add Action components to the same GameObject, then drag them into the trigger's action list. Multiple actions can be added to a single trigger.
MtdMusicControl
Controls the overall music system:
- Start — starts music and evaluates state.
- Resume — resumes from a paused state with an optional fade.
- Stop — stops music with an optional fade.
- Pause — pauses playback, preserving position, with an optional fade.
Fade Duration (ms): pass -1 to use the Project Settings default fade time.
MtdStateControl
Manipulates the state system:
- SetState — set a state value on a State Group.
- SetStateTree — replace the active State Tree.
- ClearState — reset a State Group to "None".
- ClearAllStates — reset all State Groups.
- LockState / UnlockState — prevent or allow changes to a State Group.
- LockAllStates / UnlockAllStates — lock or unlock all State Groups.
MtdSoundBankControl
Load or unload Sound Banks at runtime:
- Load — load a Sound Bank.
- Unload — unload a Sound Bank.
MtdStingerControl
Play one-shot musical stingers:
- PlayStinger — plays a stinger track.
- StopAllStingers — stops all playing stingers with a fade.
- Stinger Track
- The Music Track to play.
- Volume (dB)
- Stinger volume.
- Fade Duration
- Fade-out duration for StopAll (seconds).
- Re-Fire Behaviour
-
Parallel — multiple instances can play simultaneously.
PreventRefire — skips if the same stinger is already playing.
Interrupt — stops the existing instance and plays a new one.
MtdStopSetStart
Fades out and stops playback, executes the list of trigger actions, then starts music again. This allows high-priority actions to be triggered immediately without waiting for an active transition to complete. Use in conjunction with a high-priority State Group to immediately play important tracks without delay. Assign Trigger Action components to its action list.
Typical Setup
- Add a Trigger component (e.g.
MtdOnTriggerEnter) to a GameObject. - Add one or more Action components (e.g.
MtdStateControl) to the same GameObject. - Drag Action components into the Trigger's action list.
15 — Parameter Controllers
MtdMixerParameterController
Controls an exposed AudioMixer parameter (e.g. volume, effects sends) via the MTD system. Supports smooth fading with configurable duration and curve.
- Mixer
- The AudioMixer asset.
- Parameter Name
- The exposed parameter name (case-sensitive).
- Use Decibel Values
- If checked, interprets the target value as dB.
- Target Value
- The value to set or fade to.
- Duration
- Fade duration in seconds.
- Fade Curve
- The curve shape.
Can be triggered from code via: Trigger(), SetTargetValue(float), or TriggerWithValue(float).
MtdProximityController
Drives an MtdMixerParameterController based on distance to a target object. Useful for proximity-based audio effects like ducking, filtering, or volume changes.
- Target Method
-
PlayerTag — finds the target by tag.
SpecificTransform — direct transform reference. - Min/Max Distance
- The distance range mapped to 0–1 on the evaluation curve.
- Control Curve
- An AnimationCurve mapping normalised distance to the output value.
- Target Controller
- The MtdMixerParameterController to drive.
- Show Gizmos
- Draws distance-range spheres in the Scene view.
16 — Transition Behaviour (Runtime Detail)
This section describes the runtime behaviour of transitions in detail, covering how the system calculates timing, handles queuing, and supports cancellation.
Transition Lifecycle
When a state change occurs (e.g. via MtdApi.SetState), the system follows these steps:
- The active State Tree is evaluated to find the new matching State Outcome.
- If the new outcome matches the currently playing outcome, no action is taken.
- The TransitionRuleFinder searches for the best matching Transition Rule (see priority table). If none is found, a fallback rule is used.
- A sync point is calculated on the outgoing track's timeline.
- The sync point is adjusted forward if the transition requires lead time.
- A playback schedule is computed, determining exactly when each element (fade-out, fade-in, overlay) begins and ends.
- The incoming track is scheduled via Unity's DSP scheduling for sample-accurate timing.
- The system enters the "transitioning" state and processes fades each frame until the transition completes.
Sync Point Calculation
The sync point is the moment on the outgoing track's timeline at which the transition is anchored. It is the reference point from which all fade offsets and the incoming track's start time are calculated. All beat- and bar-relative calculations use the outgoing track's BPM, Beats Per Bar, and Beat Value to project musical time from the current playback position.
Adjusted Sync Points (Lead Time)
After the initial sync point is calculated, the system checks whether anything in the transition needs time before the sync point arrives (called "lead time"). Three sources are considered:
- Incoming track lead time — pre-roll for the incoming track's lead-in and/or negative fade-in offset, minus any position offset.
- Overlay lead time — pre-roll for the overlay track's lead-in, minus its position offset.
- Fade-out lead time — a negative fade-out offset on the outgoing track.
The largest of these is the total lead time required. If there is not enough time before the initial sync point, the system pushes it forward to the next valid occurrence of the same sync type. For the Immediate sync type, the sync point is simply moved forward by the required lead time.
Non-looping outcomes: if the outgoing track does not loop and has a fixed Play Until position, the sync point is clamped so it does not exceed this endpoint.
Pre-Roll Calculation
Pre-roll ensures that material such as a lead-in section or an early fade-in is heard at the correct moment. It is determined by comparing:
- Lead-in duration — the time between the clip start and the entry point.
- Negative fade-in offset — the absolute value of a negative fade-in offset (one that begins before the sync point).
The larger is used as the initial pre-roll. If neither applies, pre-roll is zero. Out-of-bounds protection ensures pre-roll never places the playhead before the clip start position.
The final playhead start position is: target position − pre-roll.
The final scheduled DSP time is: sync point + position offset + overlay delay − pre-roll.
Transition Queuing
Only one transition can be active at a time. If a new transition is requested while one is in progress, the system checks if it is a reversal, and if not, queues the request. Only one request can be queued at a time; a newer request replaces any previously queued one.
When the active transition finishes, the queued request is dequeued and processed. If the queued outcome matches the now-playing outcome, it is discarded.
Minimum Play Duration: if specified, no new transition fires until the duration has elapsed from the start of the incoming track's playback. Requests during this cooldown are queued.
Transition Reversal
Reversal occurs when the game state returns to the previous state combination during an active transition. The system cancels the transition and fades back to the outgoing track instead of completing the transition.
Reversal requires:
- The Transition Rule must have "Allow Transition Reversal" enabled.
- The incoming State Outcome must match the currently fading-out outcome.
- The transition must be in a phase that permits reversal (controlled by the rule's interruption flags).
State Re-Evaluation
When a transition is about to begin, the system performs a final state re-evaluation. It re-checks the current game states against the active State Tree to confirm the requested outcome is still correct. If states have changed between the initial request and processing, the system automatically corrects to the now-expected outcome. This prevents stale transitions when states change rapidly.
17 — API Reference
The public API is accessed via the static MtdApi class in the MusicTransitionDesigner.Authoring namespace.
System Control
// Start music and trigger initial state evaluation
MtdApi.StartMusic();
// Stop music with a fade. Pass -1 to use the Project Settings default.
MtdApi.StopMusic(int fadeOutMs = -1);
// Pause playback with a fade. Returns the playback time at pause.
float pauseTime = MtdApi.PauseMusic(int fadeOutMs = -1);
// Resume from pause with a fade-in.
MtdApi.ResumeMusic(int fadeInMs = -1);
State Management
// Replace the active State Tree. Provide a direct reference or GUID.
MtdApi.SetStateTree(StateTree tree = null, string treeGuid = null);
// Set a state value. Use any combination of identifiers.
MtdApi.SetState(
StateGroup group = null, string groupName = null,
string groupGuid = null, string stateName = null,
string stateGuid = null);
// Examples:
MtdApi.SetState(group: combatGroup, stateName: "InCombat");
MtdApi.SetState(groupGuid: "abc-123", stateGuid: "def-456");
MtdApi.SetState(groupName: "Location", stateName: "Area1");
// Clear a State Group (sets to None).
MtdApi.ClearState(StateGroup group = null, string groupName = null,
string groupGuid = null);
// Clear all State Groups.
MtdApi.ClearAllStates();
// Lock / unlock State Groups to prevent or allow changes.
MtdApi.LockState(...);
MtdApi.UnlockState(...);
MtdApi.LockAllStates();
MtdApi.UnlockAllStates();
// Enable or disable state evaluation.
MtdApi.EnableStateEvaluation();
MtdApi.DisableStateEvaluation();
Stingers
// Play a one-shot stinger. Provide a direct reference or GUID.
// Pass -1f for volume to use the track's authored volume.
MtdApi.PlayStinger(
MusicTrack stinger = null, string stingerGuid = null,
float volume = -1f,
StingerReFireBehaviour behaviour = StingerReFireBehaviour.Parallel);
// Stop all playing stingers with an optional fade (seconds).
MtdApi.StopAllStingers(float fadeDuration = 0f);
Sound Banks
// Get the list of currently loaded Sound Banks.
IReadOnlyList<SoundBank> banks = MtdApi.ActiveBanks;
// Load / unload Sound Banks.
MtdApi.LoadBank(SoundBank bank);
MtdApi.UnloadBank(SoundBank bank);
MtdApi.UnloadAllBanks();
Event Subscriptions
// Beat callback: bar (int), beat (int), track (MusicTrack), dspTime (double)
// Fires on every beat of the playing track (if it allows subscription).
MtdApi.SubscribeToBeat(Action<int, int, MusicTrack, double> callback);
MtdApi.UnsubscribeFromBeat(...);
// Bar callback: bar (int), track (MusicTrack). Fires on beat 1 of each bar.
MtdApi.SubscribeToBar(Action<int, MusicTrack> callback);
MtdApi.UnsubscribeFromBar(...);
// Fires when a State Outcome reaches its Play Until position (non-looping).
MtdApi.SubscribeToStateOutcomeEnd(Action<StateOutcome> callback);
MtdApi.UnsubscribeFromStateOutcomeEnd(...);
// Fires when the authoritative musical context track changes.
MtdApi.SubscribeToContextChange(Action<MusicTrack> callback);
MtdApi.UnsubscribeFromContextChange(...);
MusicTrack Properties (Callbacks & API)
When a MusicTrack is received via an event callback or retrieved from the API, these properties are available:
| Property | Type | Description |
|---|---|---|
TrackName | string | Display name. |
Bpm | double | Tempo in BPM. |
BeatsPerBar | int | Beats per bar. |
BeatValueType | enum | Eighth, Quarter, DottedQuarter, Half. |
SecondsPerBeat | double | Cached seconds per beat. |
Volume | float | Linear volume (0–1). |
VolumeDb | float | Volume in dB (−80 to 0). |
AssetGuid | string | Unique asset identifier. |
Markers | List<MusicMarker> | Track markers. |
EntryTimeInSeconds | double | Entry point time. |
ExitTimeInSeconds | double | Exit point time. |
LeadInDurationInSeconds | double | Lead-in duration. |
TailDurationInSeconds | double | Tail duration. |
ClipStartTimeInSeconds | double | Effective clip playback start. |
ClipEndTimeInSeconds | double | Effective clip playback end. |
TrackLengthInSeconds | double | Full audio clip length. |
AllowSubscriptionToBeatDefinition | bool | Whether beat/bar callbacks are active. |
Utilities
// Convert between dB and linear volume.
float linear = MtdApi.ConvertDecibelToLinear(float db);
float db = MtdApi.ConvertLinearToDecibel(float linear);
// Get the current authoritative Music Track. Null if no music is playing.
MusicTrack track = MtdApi.GetCurrentContextTrack();
18 — GUID System
MTD uses custom GUIDs (not Unity's Asset GUIDs) to provide stable runtime identifiers that survive renaming.
Asset GUIDs
The following asset types have auto-generated Asset GUIDs:
- Music Tracks — used for stinger playback via the API.
- State Groups — used for referencing groups and states via the API.
- State Trees — used for referencing trees via the API.
Individual states within a State Group and Track Markers also have their own GUIDs. GUIDs are generated automatically when an asset is first created and are serialised with the asset.
GUID Lookup
All GUIDs can be looked up via . This window displays every asset and its GUID, with a copy-to-clipboard button for easy use in code.
Duplicate GUID Detection
When an asset is duplicated (copy-paste in Unity's Project window), the copy inherits the original's GUIDs, creating a conflict. MTD detects this automatically:
- An AssetPostprocessor runs on import and flags potential duplicates with a warning dialog.
- The validation system marks assets with duplicate GUIDs as invalid.
- The Asset Manager provides a Generate New GUIDs button to resolve the conflict.
19 — Asset Relationships
Understanding how asset types depend on each other:
| Asset Type | Role |
|---|---|
| State Groups | Define game-state categories (e.g. "GamePhase") and their possible values (e.g. "Exploration", "Combat", "Boss"). |
| State Trees | Use State Groups as columns in a decision matrix. Each row maps a combination of states to a State Outcome. Only one tree is active at a time. |
| State Outcomes | Reference a Music Track and define playback parameters. They are the result of a State Tree evaluation. |
| Outcome Categories | Tag State Outcomes for use in broad Transition Rules. |
| Transition Rules | Define how playback transitions between State Outcomes. Can reference specific outcomes or entire categories. |
| Sound Banks | Package State Trees, Music Tracks, and Transition Rules for runtime loading. Dependencies are compiled automatically. |
Dependency Chain
Music Track ← State Outcome ← State Tree Entry
State Group ← State Tree Hierarchy
State Outcome ← Transition Rule
Outcome Category ← Transition Rule
State Tree ← Sound Bank
Music Track ← Sound Bank
Transition Rule ← Sound Bank
20 — Editor Validation
MTD includes a comprehensive validation system that runs automatically and flags issues in the Asset Manager.
Per-Asset Validation Rules
Music Tracks
- Must have a valid Audio Clip.
- No duplicate GUIDs.
State Groups
- Must have a unique Group Name.
- Must have at least one state.
- No duplicate state names within the group.
- No duplicate Group Names across the project.
- No duplicate GUIDs.
State Trees
- Must have at least one State Group in the hierarchy.
- All hierarchy State Groups must be valid and enabled.
- All referenced State Outcomes must be valid and enabled.
- Structural analysis: detects shadowed, partially blocked, and duplicate entries.
- No duplicate GUIDs.
State Outcomes
- Must have a valid Music Track (which must itself be valid).
- If a Category is assigned, it must be enabled.
- All marker references must point to existing markers on the track.
- Timeline logic: start position must be before end position; loop point must be before end position.
- Random Marker choices must all be before the end position.
Transition Rules
- Track A and Track B must have valid references matching their type.
- Referenced State Outcomes must be valid; referenced Categories must be enabled.
- Marker references must exist on the correct track and be within valid ranges.
- If Overlay is enabled, an Overlay Track must be assigned.
- No conflicting rule definitions; bidirectional rules are checked for reverse-path conflicts.
Sound Banks
- Must have at least one source (State Tree or Music Track).
- All sources must be valid and enabled.
- Warns if compilation skipped invalid/disabled assets.
Cascading Validation
Validation cascades through the dependency chain. If a Music Track becomes invalid, all State Outcomes referencing it become invalid, which in turn invalidates any State Trees and Transition Rules that reference those outcomes. The Asset Manager reflects these cascading errors.
Deleted Asset Cleanup
The editor automatically detects and cleans up references to deleted assets across all dependent assets.
21 — Troubleshooting
Music Not Playing
- Ensure MtdSceneInitialiser is present in the scene.
- Check that at least one Sound Bank is loaded (via SceneInitialiser or API).
- Verify that the Sound Bank's sources are valid (check for validation errors in the Asset Manager).
- Ensure a State Tree is active and its entries have valid State Outcomes.
- Check that audio files are marked as Addressable.
- Look for warnings/errors in the Unity Console (ensure logging is enabled in Project Settings).
Transitions Not Firing
- Verify that a Transition Rule exists for the current transition path.
- Check that the Transition Rule is enabled.
- Ensure the rule is included in a loaded Sound Bank.
- Check for rule conflicts (duplicate definition warnings in the Asset Manager).
Invalid Assets
- Check for duplicate GUIDs (caused by copy-pasting assets). Use Generate New GUIDs.
- Validation cascades: a single invalid Music Track can invalidate all dependent assets. Fix the root cause and dependent assets will become valid again.
- Ensure all referenced assets (tracks, groups, outcomes, categories) exist and are enabled.
Beat/Bar Callbacks Not Firing
- Ensure the playing Music Track has Allow Subscription To Beat Definition enabled.
- Check that you have subscribed using the correct API method (
SubscribeToBeatorSubscribeToBar). - Verify music is actually playing (not paused or stopped).
Stingers Not Playing
- Ensure the stinger's Music Track is included in a loaded Sound Bank.
- Verify the audio clip is loaded (the bank must be fully loaded before stingers work).
- Check re-fire behaviour: PreventRefire will block a stinger if it's already playing.
Music Transition Designer © 2024–2026 Josh Winiberg. All rights reserved.
Support: contact@joshwiniberg.co.uk