DEV505 / API REFERENCE
SoundBus
The entry point for playing and controlling sound through the active Sound Manager.
namespace DEV505.SoundManager{ public static class SoundBus}New to the terms on this page? An event is a saved sound recipe, a play is one running copy, and a handle is the value you keep to control that copy. Start with Your first sound for a complete script and scene setup. The blocks below are reference signatures or labeled excerpts, not separate scripts to attach to objects.
Before calling
Section titled “Before calling”Add the event to the active manager’s Direct events or Libraries list before Play Mode. Call this API on Unity’s main thread, for example from Start, Update, or a button callback. Commands dispatched from a worker thread to the built-in service return InvalidContext. Query helpers are not safe to call from a worker thread either.
A missing manager returns NoManager from dispatch/play and logs a warning once per play session. It does not buffer requests until a manager appears. An existing manager may admit a play as Queued while clips prepare or while a request waits for the current tick to finish.
public static SoundPlayResult Play( SoundKey key, in SoundPlayContext context = default);public static SoundPlayResult Play(SoundKey key, Vector3 position);public static SoundPlayResult Play(SoundKey key, Transform follow);public static SoundPlayResult Play( SoundEvent sound, in SoundPlayContext context = default);| Argument | Meaning |
|---|---|
key |
The registered name of the event. Prefer generated Sounds.* values. An unknown key gives NotRegistered. |
context |
Optional per-play position/follow target, owner, initial overrides, seed, and delay. A default context has no follow target or owner and uses its zero position. |
position |
Fixed world point. The sound remains there if the object that caused it moves away. |
follow |
Transform tracked while the play runs. This convenience overload also owns the play by follow.gameObject. |
sound |
An event asset reference. It still needs registration on the active manager, and the same validation and preparation rules apply. |
Returns SoundPlayResult: Status describes admission and Handle identifies an accepted play. Accepted is true for both Accepted and Queued. An accepted request is not a guarantee that a voice is already audible or that the play can never subsequently fail.
var context = SoundPlayContext.At(footPosition) .With(SoundParameters.Footstep.Surface, 1); // Stone in this graphvar result = SoundBus.Play(Sounds.Footstep, context);This excerpt requires a registered Footstep event and a Vector3 footPosition. Initial overrides are applied before On Start, so the first branch sees the intended surface. The scene’s surface enum has a different numbering; map it to the graph value rather than casting directly.
var service = SoundServices.Current;if (service == null) return;
var owner = service.OwnerOf(gameObject);var context = SoundPlayContext.Following(transform, owner) .With(SoundParameters.Campfire.Intensity, 0.35f);var result = SoundBus.Play(Sounds.Campfire, context);This belongs inside a MonoBehaviour method. Keep the accepted handle if you need later control. .Following(transform) by itself does not acquire the same automatic GameObject owner as Play(key, transform); pass an owner when constructing the context if you need owner-wide commands. A destroyed follow target is also handled by the event’s loss policy.
.With(...) returns a new struct value. Keep the returned context; calling it without assigning/chaining discards the override. Up to four inline overrides are supported. More require TypedParameters or an appropriate service API. Float-array overrides apply first, then typed-array overrides, then inline values.
The complete Campfire component shows accepted-result handling and cleanup.
public static bool Stop(SoundHandle handle, float fade = 0.1f);handle identifies the play; fade is seconds and must be finite and non-negative. Returns true when the service accepts the stop, false for a missing manager, invalid/stale target, or invalid request.
For a started play, stopping runs On Stop, then fades remaining pre-existing voices. Voices created by the stop branch can continue as release audio. A node explicitly stopped through its graph Stop port uses that node’s authored fade-out. A queued play that never started is cancelled without a normal started-play release. The return value does not mean all audio is now silent.
SoundBus.Stop(fire, fade: 0.15f);Here fire is a handle retained from a previous accepted play. Do not assume changing this fallback fade changes the duration of every authored release cue.
StopAll
Section titled “StopAll”public static int StopAll(UnityEngine.Object source, float fade = 0.1f);Returns the number of plays reached through that object’s existing owner token. Zero means no eligible plays were reached, including when no manager or owner exists. The method does not create an owner record merely to perform a no-op. It uses the same stop/fade semantics as per-handle stop.
// Play(key, transform) uses the transform's GameObject as owner.SoundBus.Play(Sounds.Campfire, transform);
// Later:int stopped = SoundBus.StopAll(gameObject);Pass gameObject for that convenience play, not an unrelated component. A context with an explicit different owner must be addressed through that owner’s identity/service methods.
SetFloat
Section titled “SetFloat”public static bool SetFloat( SoundHandle handle, SoundParameterId parameter, float value);public static bool SetFloat( SoundHandle handle, string name, float value);public static int SetFloat( UnityEngine.Object source, string name, float value);Sets a live float parameter’s target. Prefer the generated parameter ID for repeated writes; string overloads match by name. Declared numeric ranges clamp accepted values, and the graph parameter’s rise/fall rates determine smoothing. A wrong type, missing parameter, non-finite value, or dead target is refused.
Per-handle overloads return whether the update was accepted. The source overload returns how many owned plays accepted it. A false/zero result does not reveal a detailed rejection reason through this shortcut.
SoundBus.SetFloat(fire, SoundParameters.Campfire.Intensity, 0.35f);Campfire’s initial branch and ignition may already have run by this point. Use the play context for values required during On Start.
SetParameter
Section titled “SetParameter”public static bool SetParameter( SoundHandle handle, SoundParameterId parameter, SoundValue value);Sets a declared parameter with an explicit type. Returns whether the service accepted the update. The type must match; audio-asset values must be among the event’s allowed assets. Numeric values are subject to the declared range. This method does not add a new parameter to a graph.
SoundBus.SetParameter(workshop, SoundParameters.Workshop.Tool, SoundValue.Int(2)); // DrillThis excerpt assumes workshop is the retained handle of a running Workshop event. Use SoundValue.Float, .Int, .Bool, or .Asset for the declared type. Initial typed values can also be passed through SoundPlayContext.With before playback begins.
SendSignal
Section titled “SendSignal”public static bool SendSignal(SoundHandle handle, SoundSignalId signal);public static bool SendSignal(SoundHandle handle, string signal);public static int SendSignal(UnityEngine.Object source, string signal);Queues a named graph action on existing plays. It does not start another play. The per-handle forms return whether the signal was accepted; the source form counts plays that accepted it. A missing signal, ended or stopping play, or full signal queue gives false/zero. The graph processes an accepted signal on the next service update; the call does not promise a recording has already started.
SoundBus.SendSignal(engine, "Horn");engine must identify a running Engine event. For repeated calls, resolve the ID once from its event with SoundEvent.GetSignalId("Horn"), check IsValid, then use the ID overload. Campfire has no signal entry points in its current graph.
IsAlive
Section titled “IsAlive”public static bool IsAlive(SoundHandle handle);Returns whether the active service still owns this play. Returns false for a default, finished, stale-session, or stale-generation handle, or without a manager. A queued or stopping play can remain alive while it still exists. Liveness is not the same as audibility, and SoundHandle.IsValid alone is not a liveness test.
if (SoundBus.IsAlive(fire)) return;SetPaused
Section titled “SetPaused”public static bool SetPaused(SoundHandle handle, bool paused);Returns whether the request was accepted. true pauses that play; false resumes it. Per-play pause is separate from service/listener pause. Resuming a play does not override an applicable global pause. Missing or dead targets return false. If your interaction retains two plays—for example, a crossfade—address both handles.
SoundBus.SetPaused(fire, true);// Later:SoundBus.SetPaused(fire, false);TryResolve
Section titled “TryResolve”public static bool TryResolve(SoundKey key, out SoundEvent sound);Returns true and the registered event when the current manager resolves the key. Otherwise returns false with sound set to null. Useful for content validation or resolving a signal ID; Play(key, ...) already performs the lookup itself. Successful resolution is not a play request and does not imply a voice is running.
if (SoundBus.TryResolve(Sounds.Engine, out var eventAsset)){ var horn = eventAsset.GetSignalId("Horn"); if (horn.IsValid) SoundBus.SendSignal(engine, horn);}Dispatch
Section titled “Dispatch”public static SoundPlayResult Dispatch(in SoundRequest request);All the command shortcuts above route through dispatch. Use it when code already works with SoundRequest values, or when you want a status instead of a shortcut’s bool/count. It supports play, stop, owner-wide stop, parameter, signal, pause, and resume requests.
var request = SoundRequest.Stop(fire, 0.15f);var result = SoundBus.Dispatch(request);Debug.Log(result.Status);For control requests, Accepted means at least one target was reached; otherwise the bus commonly reports NoTarget. Individual service validation failures may be collapsed into NoTarget by these control shortcuts. Do not assume every false parameter/stop result gives the exact underlying cause through dispatch. An off-thread dispatched request against the concrete service reports InvalidContext.
Notifications
Section titled “Notifications”public static SoundNotifications Notifications { get; }Use Subscribe(Action<SoundNotification>) and dispose its returned token when the listener is disabled/destroyed. Subscribing through the bus follows replacement of the active service. It reports admission/start/termination from all plays, so filter by the relevant handle/event instead of treating every notification as yours.
private System.IDisposable subscription;
private void OnEnable(){ subscription = SoundBus.Notifications.Subscribe(notification => { if (notification.IsTerminal) Debug.Log($"{notification.Kind}: {notification.Reason}"); });}
private void OnDisable(){ subscription?.Dispose(); subscription = null;}This excerpt observes every ending, cancellation, and failure, including other objects’ sounds. Subscribe(null) throws ArgumentNullException; duplicate delegates are not added twice. Do not add a second OnDisable method to the complete Campfire recipe—combine cleanup into its existing method. The built-in service delivers notifications at the end of its update; subscribe before playing, then save the returned handle. The complete Engine example shows how to filter messages for one play.
Results and rejections
Section titled “Results and rejections”| Status | Meaning |
|---|---|
Accepted |
Started/admitted immediately, or a control command reached a target. |
Queued |
Admitted for a later tick or clip readiness. result.Accepted is still true. |
NoManager |
No active playback service; nothing is buffered. |
NotRegistered |
No matching registered key/event. |
InvalidEvent |
Invalid graph or runtime graph failure. |
NotReady |
Service shut down, or startup wait expired. |
MissingClip |
Required clip is absent or failed to load. |
ConcurrencyLimit |
Event instance limit refused/replaced a play. |
CapacityExceeded |
No available slot, start-queue room, or voice. |
InvalidContext |
Invalid position/delay/owner/parameter or dispatched call from another thread. |
Cooldown |
The event was requested again too soon. |
NoTarget |
The control request did not reach a live eligible play. |
A playback result reports admission; later failures and cancellations are reported through notifications. Every status above comes from the current enum, not a planned API.
Next steps
Section titled “Next steps”Try the complete lifecycle recipe or follow the Campfire graph walkthrough.