$npx -y skills add quodsoler/unreal-engine-skills --skill ue-audio-systemUse this skill when working with audio, sound, music, UAudioComponent, PlaySoundAtLocation, SoundCue, MetaSound, attenuation, submix, concurrency, SFX, or spatial audio in Unreal Engine. See references/audio-setup-patterns.md for music system and ambient soundscape architectures.
| 1 | # UE Audio System |
| 2 | |
| 3 | You are an expert in Unreal Engine's audio systems, covering UAudioComponent, sound asset types, |
| 4 | spatial attenuation, concurrency management, submix routing, MetaSounds, and runtime audio analysis. |
| 5 | |
| 6 | ## Context Check |
| 7 | |
| 8 | Before implementing audio, read `.agents/ue-project-context.md` for: |
| 9 | |
| 10 | - **Audio plugins** enabled (Resonance Audio, Steam Audio, Wwise, FMOD, MetaSound plugin version) |
| 11 | - **Target platforms** — mobile has strict voice limits; consoles differ from PC |
| 12 | - **Dedicated server** flag — audio must be skipped server-side or it will crash/log errors |
| 13 | - **VR flag** — VR projects require binaural spatialization settings |
| 14 | |
| 15 | ## Information Gathering |
| 16 | |
| 17 | Ask about: |
| 18 | |
| 19 | 1. One-shot SFX, looping ambient, music, UI feedback, or dialogue? |
| 20 | 2. Spatialized (follows actor) or global 2D? |
| 21 | 3. Concurrency concern (gunshots, footsteps, explosions)? |
| 22 | 4. Runtime control needed (fade, pause, parameter changes)? |
| 23 | 5. MetaSound procedural or pre-authored SoundCue/SoundWave? |
| 24 | |
| 25 | --- |
| 26 | |
| 27 | ## Sound Asset Hierarchy |
| 28 | |
| 29 | ``` |
| 30 | USoundBase // abstract base (SoundBase.h) |
| 31 | ├── USoundWave // raw PCM/compressed audio asset |
| 32 | ├── USoundCue // node-graph: random, modulator, mixer, attenuator nodes |
| 33 | └── UMetaSoundSource // procedural audio graph (MetaSound plugin) |
| 34 | ``` |
| 35 | |
| 36 | **USoundWave** — Import .wav/.ogg/.flac. Set `SoundClassObject` and `AttenuationSettings` on asset. |
| 37 | |
| 38 | **USoundCue** — Node graph combining multiple waves. Key nodes: |
| 39 | `USoundNodeRandom`, `USoundNodeModulator`, `USoundNodeMixer`, `USoundNodeAttenuation`, |
| 40 | `USoundNodeLooping`, `USoundNodeDelay`, `USoundNodeDistanceCrossFade`. |
| 41 | |
| 42 | **UMetaSoundSource** — Procedural audio graph. Declare typed inputs (float, bool, int32, trigger). |
| 43 | Set parameters at runtime via `UAudioComponent::SetFloatParameter`, `SetBoolParameter`, `SetIntParameter`. |
| 44 | |
| 45 | ### Streaming Long Audio |
| 46 | |
| 47 | For music and ambient tracks exceeding ~30 seconds, set `USoundWave::LoadingBehavior`: |
| 48 | `ESoundWaveLoadingBehavior::ForceInline` for short SFX, `RetainOnLoad` for music loaded at level start. |
| 49 | Long files should use `LoadOnDemand` to avoid loading the full waveform into memory. |
| 50 | In the editor: SoundWave asset → Details → Loading → Loading Behavior. |
| 51 | |
| 52 | --- |
| 53 | |
| 54 | ## Playing Sounds from C++ |
| 55 | |
| 56 | ### Fire-and-Forget |
| 57 | |
| 58 | ```cpp |
| 59 | #include "Kismet/GameplayStatics.h" |
| 60 | |
| 61 | // 2D — not spatialized (UI, music) |
| 62 | UGameplayStatics::PlaySound2D( |
| 63 | this, ImpactSound, 1.0f /*Vol*/, 1.0f /*Pitch*/, 0.0f /*StartTime*/, |
| 64 | ConcurrencySettings, OwningActor |
| 65 | ); |
| 66 | |
| 67 | // 3D — spatialized, requires AttenuationSettings on the sound asset |
| 68 | UGameplayStatics::PlaySoundAtLocation( |
| 69 | this, GunShotSound, GetActorLocation(), FRotator::ZeroRotator, |
| 70 | 1.0f, 1.0f, 0.0f, |
| 71 | AttenuationOverride, // USoundAttenuation* (nullptr = use asset default) |
| 72 | ConcurrencyOverride, // USoundConcurrency* (nullptr = use asset default) |
| 73 | this // OwningActor for per-owner concurrency |
| 74 | ); |
| 75 | ``` |
| 76 | |
| 77 | ### Spawn with Handle |
| 78 | |
| 79 | ```cpp |
| 80 | // Returns UAudioComponent* — auto-destroyed when sound finishes if bAutoDestroy=true |
| 81 | UAudioComponent* Comp = UGameplayStatics::SpawnSoundAtLocation( |
| 82 | this, ExplosionSound, Location, FRotator::ZeroRotator, |
| 83 | 1.0f, 1.0f, 0.0f, AttenuationSettings, nullptr, /*bAutoDestroy=*/true |
| 84 | ); |
| 85 | |
| 86 | // Attach to a moving component (vehicle engine) |
| 87 | UAudioComponent* EngineAudio = UGameplayStatics::SpawnSoundAttached( |
| 88 | EngineLoopSound, GetMesh(), NAME_None, |
| 89 | FVector::ZeroVector, FRotator::ZeroRotator, |
| 90 | EAttachLocation::SnapToTargetIncludingScale, |
| 91 | /*bStopWhenAttachedToDestroyed=*/true, |
| 92 | 1.0f, 1.0f, 0.0f, AttenuationSettings, nullptr, |
| 93 | /*bAutoDestroy=*/false // keep alive for looping |
| 94 | ); |
| 95 | ``` |
| 96 | |
| 97 | ### UAudioComponent as Permanent Actor Component |
| 98 | |
| 99 | ```cpp |
| 100 | // In constructor: |
| 101 | AudioComponent = CreateDefaultSubobject<UAudioComponent>(TEXT("AudioComponent")); |
| 102 | AudioComponent->SetupAttachment(RootComponent); |
| 103 | AudioComponent->bAutoActivate = false; |
| 104 | AudioComponent->bStopWhenOwnerDestroyed = true; |
| 105 | ``` |
| 106 | |
| 107 | ### Playback Control |
| 108 | |
| 109 | ```cpp |
| 110 | AudioComponent->SetSound(EngineLoopSound); |
| 111 | AudioComponent->Play(/*StartTime=*/0.0f); |
| 112 | AudioComponent->Stop(); |
| 113 | AudioComponent->SetPaused(true); |
| 114 | AudioComponent->FadeIn(0.5f, 1.0f, 0.0f, EAudioFaderCurve::Linear); |
| 115 | AudioComponent->FadeOut(1.0f, 0.0f, EAudioFaderCurve::Linear); |
| 116 | AudioComponent->SetVolumeMultiplier(0.5f); |
| 117 | AudioComponent->SetPitchMultiplier(1.2f); |
| 118 | |
| 119 | // Query play state (EAudioComponentPlayState: Playing, Stopped, Paused, FadingIn, FadingOut) |
| 120 | EAudioComponentPlayState State = AudioComponent->GetPlayState(); |
| 121 | ``` |
| 122 | |
| 123 | ### Delegates (AudioComponent.h) |
| 124 | |
| 125 | ```cpp |
| 126 | // Declared in AudioComponent.h: |
| 127 | // DECLARE_D |