Skip to main content

Multiplayer Guide


Quick Reference

GoalSetup
Zone music (forest, cave, tavern)Place ERP_MusicVolume
Zone music synced between playersEnable Network Sync on the volume
Global music (boss fight, cutscene)SyncComponent → SyncPushMusicLayer
Local stinger (pickup, UI)AERP_StingerVolume, scope = Local Only
Stinger for all playersAERP_StingerVolume, scope = Everyone

Music Volumes

Default — Local Playback

Each player triggers volumes independently when they enter. No network traffic.

Setup: Place ERP_MusicVolume in your level. Done.

Network Sync — Time-Synced Playback

Music still plays locally per player, but playback position is synchronized. A player entering 30 seconds after another hears the music at the 30-second mark.

Setup: Enable Music | Behavior → Network Sync on the volume.

Trigger Modes

ModeBehavior
ToggleEnter = start, leave = stop
EnableOne-shot start on entry
DisableOne-shot stop on entry

Actor Filter Tag — Only actors with the specified GameplayTag trigger the volume.


Stinger Volumes

Network Scope

ScopeBehavior
Local OnlyOnly the entering player hears the stinger
EveryoneAll clients hear the stinger when any player enters

Spatialization

ModeBehavior
2D (Flat)Same volume everywhere
3D (Localized)Positioned at volume center with distance attenuation

3D stingers remain active when the listener moves far away. The sound attenuates with distance but continues playing, so returning players hear it at the correct position.

Runtime Control

FunctionDescription
StopStinger()Stop the currently playing stinger

Example: Tavern Door Bell

  1. Place AERP_StingerVolume at the door
  2. StingerSound → bell sound
  3. Network ScopeEveryone
  4. Spatialization3D (Localized)
  5. Attenuation Start Distance2000.0
  6. Trigger Oncefalse

Global Music Sync

For music that all clients should hear regardless of location.

Use the ERP Music Helper functions — they work from server or client with automatic routing:

Sync Push Music Layer (LayerName, Music, Priority, ...)   ← all clients play
Sync Pop Music Layer (LayerName) ← all clients stop
Sync Clear All Layers ← stop everything
Sync Play Stinger (StingerSound, ...) ← all clients hear
Sync Stop Stinger (Handle) ← all clients stop

Tag-based variants:

Sync Push Music Layer By Tag (Tag)
Sync Pop Music Layer By Tag (Tag)

No need to get the subsystem or SyncComponent manually. No need to check authority — the helpers route the call through the network automatically.

Example: Boss Phase Music

Event "Enter Phase 2"

Sync Pop Music Layer ("BossPhase1")

Sync Push Music Layer ("BossPhase2")

All clients switch music. Late-joiners hear it at the correct offset.

Example: Victory Stinger

Event "Boss Defeated"

Sync Clear All Layers

Sync Play Stinger (VictoryFanfare)

Example: Tag-Based

Event "Enter Dungeon"

Sync Push Music Layer By Tag (Music.Zone.Dungeon)

Advanced: Direct SyncComponent Access

For fine-grained control, access the SyncComponent directly (server authority required):

Get Music Subsystem → Get Or Create Sync Component → Sync Push Music Layer

C++

UERP_MusicSubsystem* MusicSys = GetGameInstance()->GetSubsystem<UERP_MusicSubsystem>();
if (UERP_MusicSyncComponent* SyncComp = MusicSys->GetOrCreateSyncComponent())
{
SyncComp->SyncPushMusicLayer(BossLayer);

FERP_EnhancedStingerParams Params;
Params.StingerSound = VictoryStinger;
FERP_StingerHandle Handle = SyncComp->SyncPlayStinger(Params);

SyncComp->SyncStopStinger(Handle);
}

SyncComponent Functions

FunctionDescription
SyncPushMusicLayer(Layer, Quantization)Push a layer on all clients
SyncPopMusicLayer(LayerName, Quantization)Remove a layer on all clients
SyncClearAllLayers()Stop all synced music
SyncPlayStinger(Params)StingerHandlePlay a stinger on all clients
SyncStopStinger(Handle)Stop a synced stinger
GetSyncedLayerNames()Query active synced layers
GetSyncedStingerHandles()Query active synced stingers

How It Works

Replication

The UERP_MusicSyncComponent lives on GameState and replicates SyncedLayers[] and SyncedStingers[] to all clients. When these arrays change, OnRep callbacks trigger local playback on each client. No audio is streamed — each client loads assets from disk.

A UERP_MusicNetRelay component is auto-created on each PlayerController to route client-initiated sync calls to the server. The Blueprint helpers use this automatically — you never need to interact with it directly.

Late-Joiner Sync

All timing uses GetServerWorldTimeSeconds(). When a client joins mid-session, it receives the current synced state and calculates the correct playback offset automatically.

Local vs Synced Layers

Local layers (from volumes, direct PushMusicLayer calls) and synced layers (from SyncComponent) coexist independently. Synced replication never affects local layers.

Background Audio

Synced music continues playing when the game window loses focus, keeping all clients in sync.


Best Practices

  • Use Music Volumes for zone-based music — automatic, no network traffic
  • Use Network Sync on volumes when players in the same area should hear the same beat
  • Use Sync helpers (Sync Push Music Layer, etc.) for global events — they work from server or client
  • Use tag-based sync (Sync Push Music Layer By Tag) for organized projects
  • Test with PIE multiplayer (Number of Players: 2+)

Troubleshooting

Music doesn't play on clients

Ensure you're not calling PushMusicLayer inside a HasAuthority() block. Either call locally or use a Multicast RPC.

Synced music plays outside the volume

This is expected for SyncComponent calls — they play globally. Use ERP_MusicVolume with Network Sync for area-restricted music.

SyncComponent returns nullptr

The GameState may not exist yet. The subsystem retries automatically. Avoid calling sync functions in BeginPlay of very early actors.


Summary

FeatureNetwork Traffic
Music VolumesNone
Music Volumes (Network Sync)None (shared clock)
SyncComponent LayersMinimal
Stinger Volumes (Local Only)None
Stinger Volumes (Everyone)Minimal
SyncComponent StingersMinimal
Audio DuckingNone
Volume ControlNone

Further Reading