Guidance / API reference
Netcode (Multiplayer)
Namespace: AudioSystem.Netcode
Assemblies: SFXSystem.Netcode (core, references Runtime only) · SFXSystem.Netcode.Ngo / .FishNet (adapters, auto-gated on their package)
Backend-agnostic networked audio. See the User Guide → Multiplayer (Netcode) for concepts, setup, and the mental model. No audio crosses the wire — only a ~36-byte descriptor.
NetworkedAudioManager
The static gameplay façade.
| Method | Description |
|---|---|
AudioHandle PostNetworkedEvent(string eventName, Vector3 position, GameObject emitter = null, bool? independentVariation = null) |
One-shot: plays locally now (echo) + relays to other peers. Returns the local handle. emitter attaches it to a moving networked object (null = static). independentVariation: null = the event’s authored default; true/false = override. Warns + plays local-only if the event has no stable ID. |
AudioHandle PostNetworkedEvent(int stableId, …) |
Same, by stable ID. |
NetworkedSoundHandle PostNetworkedLoop(string eventName, Vector3 position, GameObject emitter = null, bool? independentVariation = null) |
Starts a shared persistent (loop) sound tracked for stop, culling + late-join (phase per the event’s Loop Sync Tier). Returns a handle carrying the shared instance ID + the local echo. On a dedicated server, warns and redirects to PostServerLoop. |
void StopNetworked(NetworkedSoundHandle handle) |
Stops the local echo now and broadcasts the stop (scope All for server-authored, else Others). Safe on a null / pure-local handle. |
AudioHandle PostServerEvent(string / int, …) |
Server-authored one-shot to everyone (scope All), no local echo. Warns + no-ops on a client. Off-session → plain local play. |
NetworkedSoundHandle PostServerLoop(string eventName, …) |
Server-authored loop to everyone; handle’s Local is null, ServerAuthored is true. Tracked for late-join. |
AudioHandle PostNetworkedScheduled(string / int, Vector3 position, double networkTime, …) |
Fire at a shared network time; returns the scheduled local echo. Warns if the event name/id is unknown. |
void PostServerScheduled(string / int, …, double networkTime, …) |
Server-authored scheduled one-shot (scope All). |
AudioHandle PostNetworkedQuantized(string, Vector3, Quantize, …) |
Schedule on the next beat/bar of the shared musical grid. Requires a transport (SetTempo); warns + returns null otherwise. |
void PostServerQuantized(string, Vector3, Quantize, …) |
Server-authored quantized cue. |
void ResyncClock() |
Force the network clock to hard-re-sample its offset next tick. |
NetworkedSoundHandle
| Member | Description |
|---|---|
ulong InstanceId |
Shared cross-client identity, `(ownerClientId << 32 |
AudioHandle Local |
The instigator’s local-echo handle. Null off-session and for server-authored / Tier-2 loops. |
bool IsValid |
True when InstanceId != 0. |
bool ServerAuthored |
True for PostServerLoop — selects the stop scope (All). |
NetworkMusicTransport & NetworkClock
NetworkMusicTransport (static) — shared tempo/phase:
| Member | Description |
|---|---|
void SetTempo(double bpm, int beatsPerBar) |
Server only. Author the transport; networked on change, replayed to late joiners. A mid-session change re-anchors seamlessly at the next bar. |
bool IsSet · double Bpm · int BeatsPerBar · double PhaseAnchor |
Current grid state (PhaseAnchor = network time of beat 0). |
double NextBeatNetworkTime(double from) / NextBarNetworkTime(double from) |
The next grid slot ≥ from, in network time. |
NetworkClock (static) — network-time ↔ local dsp:
| Member | Description |
|---|---|
double NetworkTime |
This machine’s current network time (synced server time; local dsp off-session). |
double NetworkToLocalDsp(double t) |
Map a network-time target to local AudioSettings.dspTime for PlayScheduled. |
void ResyncClock() |
Force a hard re-sample of the offset. |
NetworkAudioSettings
MonoBehaviour — scene config + game-supplied hooks.
| Member | Description |
|---|---|
bool ProximityCulling |
Opt into culling. Default off. |
Func<ulong, Vector3?> ListenerPositionProvider |
Game-supplied per-client listener position (server calls it). Null → culling inert. Assigned in code. |
NetworkAudioValidator ServerValidator |
Server-side authority gate. Null → allow-all. Assigned in code. |
float DefaultAudibleRadius · float LoopReevalSeconds |
Culling fallback radius + loop re-eval rate. |
| clock/lead tunables | ClockSmoothing, ClockResyncThreshold, ScheduleLeadFloor, ScheduleLeadRttFactor. |
NetworkAudioEvent & NetworkAudioScope
NetworkAudioEvent (struct) — the wire payload:
| Field | Description |
|---|---|
int EventId |
The AudioEvent.StableId to play. |
Vector3 Position |
World position — also the emitter fallback/anchor. |
ulong EmitterNetId |
Optional network-object id to attach to. 0 = static. |
ulong InstanceId |
Shared identity for a persistent/loop sound. 0 = a one-shot. |
int Seed |
Variation seed. Non-zero forces the SAME variant on every client; 0 = independent. |
Plus Pack / Unpack — the canonical 36-byte wire format (round-trip covered by NetworkAudioEventPackTests).
NetworkAudioScope (enum): Others (default — everyone but the sender) · All (server-authored) · Owner (reserved) · Proximity (reserved enum value; culling is realised on the Others/All paths as “don’t send”). Passing an unhonored scope logs a warning and relays as Others.
Per-event authoring (AudioEvent, Multiplayer foldout, shown only with a backend installed): Unreliable Delivery, Independent Variation (default), Loop Sync Tier (0/1/2; Tier 2 is experimental — see User Guide §17.4). For the INetworkAudioTransport boundary — implementing a new backend — see User Guide §17.9.
From the Pepper.SFX 3.1 guides (API_REFERENCE.md). Something wrong or unclear? Tell me.