[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6FEPTYWA6M5WF9C1GFM2BTZ":3,"skill-same:01M6FEPTYWA6M5WF9C1GFM2BTZ":53},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":26,"linkOnly":27,"markdownContent":28,"markdownBody":28,"frontMatter":29,"refName":30,"commitSha":31,"skillDirectory":32,"forksCount":33,"repositoryHtmlUrl":34,"repositoryHomepageUrl":35,"ownerHtmlUrl":36,"ownerBlogUrl":6,"ownerDescription":37,"updatedAt":38,"install":39,"resources":52},"01M6FEPTYWA6M5WF9C1GFM2BTZ","ue-audio-system",null,"ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",66,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fquodsoler\u002Funreal-engine-skills\u002Fue-audio-system\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000016","图像与多媒体","SCENARIO","使用场景",[23,24,25],"Audio","system","ue audio system","2026-11-10 10:12:30",false,"# UE Audio System\n\nYou are an expert in Unreal Engine's audio systems, covering UAudioComponent, sound asset types,\nspatial attenuation, concurrency management, submix routing, MetaSounds, and runtime audio analysis.\n\n## Context Check\n\nBefore implementing audio, read `.agents\u002Fue-project-context.md` for:\n\n- **Audio plugins** enabled (Resonance Audio, Steam Audio, Wwise, FMOD, MetaSound plugin version)\n- **Target platforms** — mobile has strict voice limits; consoles differ from PC\n- **Dedicated server** flag — audio must be skipped server-side or it will crash\u002Flog errors\n- **VR flag** — VR projects require binaural spatialization settings\n\n## Information Gathering\n\nAsk about:\n\n1. One-shot SFX, looping ambient, music, UI feedback, or dialogue?\n2. Spatialized (follows actor) or global 2D?\n3. Concurrency concern (gunshots, footsteps, explosions)?\n4. Runtime control needed (fade, pause, parameter changes)?\n5. MetaSound procedural or pre-authored SoundCue\u002FSoundWave?\n\n---\n\n## Sound Asset Hierarchy\n\n```\nUSoundBase                    \u002F\u002F abstract base (SoundBase.h)\n  ├── USoundWave              \u002F\u002F raw PCM\u002Fcompressed audio asset\n  ├── USoundCue               \u002F\u002F node-graph: random, modulator, mixer, attenuator nodes\n  └── UMetaSoundSource        \u002F\u002F procedural audio graph (MetaSound plugin)\n```\n\n**USoundWave** — Import .wav\u002F.ogg\u002F.flac. Set `SoundClassObject` and `AttenuationSettings` on asset.\n\n**USoundCue** — Node graph combining multiple waves. Key nodes:\n`USoundNodeRandom`, `USoundNodeModulator`, `USoundNodeMixer`, `USoundNodeAttenuation`,\n`USoundNodeLooping`, `USoundNodeDelay`, `USoundNodeDistanceCrossFade`.\n\n**UMetaSoundSource** — Procedural audio graph. Declare typed inputs (float, bool, int32, trigger).\nSet parameters at runtime via `UAudioComponent::SetFloatParameter`, `SetBoolParameter`, `SetIntParameter`.\n\n### Streaming Long Audio\n\nFor music and ambient tracks exceeding ~30 seconds, set `USoundWave::LoadingBehavior`:\n`ESoundWaveLoadingBehavior::ForceInline` for short SFX, `RetainOnLoad` for music loaded at level start.\nLong files should use `LoadOnDemand` to avoid loading the full waveform into memory.\nIn the editor: SoundWave asset → Details → Loading → Loading Behavior.\n\n---\n\n## Playing Sounds from C++\n\n### Fire-and-Forget\n\n```cpp\n#include \"Kismet\u002FGameplayStatics.h\"\n\n\u002F\u002F 2D — not spatialized (UI, music)\nUGameplayStatics::PlaySound2D(\n    this, ImpactSound, 1.0f \u002F*Vol*\u002F, 1.0f \u002F*Pitch*\u002F, 0.0f \u002F*StartTime*\u002F,\n    ConcurrencySettings, OwningActor\n);\n\n\u002F\u002F 3D — spatialized, requires AttenuationSettings on the sound asset\nUGameplayStatics::PlaySoundAtLocation(\n    this, GunShotSound, GetActorLocation(), FRotator::ZeroRotator,\n    1.0f, 1.0f, 0.0f,\n    AttenuationOverride,    \u002F\u002F USoundAttenuation* (nullptr = use asset default)\n    ConcurrencyOverride,    \u002F\u002F USoundConcurrency* (nullptr = use asset default)\n    this                    \u002F\u002F OwningActor for per-owner concurrency\n);\n```\n\n### Spawn with Handle\n\n```cpp\n\u002F\u002F Returns UAudioComponent* — auto-destroyed when sound finishes if bAutoDestroy=true\nUAudioComponent* Comp = UGameplayStatics::SpawnSoundAtLocation(\n    this, ExplosionSound, Location, FRotator::ZeroRotator,\n    1.0f, 1.0f, 0.0f, AttenuationSettings, nullptr, \u002F*bAutoDestroy=*\u002Ftrue\n);\n\n\u002F\u002F Attach to a moving component (vehicle engine)\nUAudioComponent* EngineAudio = UGameplayStatics::SpawnSoundAttached(\n    EngineLoopSound, GetMesh(), NAME_None,\n    FVector::ZeroVector, FRotator::ZeroRotator,\n    EAttachLocation::SnapToTargetIncludingScale,\n    \u002F*bStopWhenAttachedToDestroyed=*\u002Ftrue,\n    1.0f, 1.0f, 0.0f, AttenuationSettings, nullptr,\n    \u002F*bAutoDestroy=*\u002Ffalse   \u002F\u002F keep alive for looping\n);\n```\n\n### UAudioComponent as Permanent Actor Component\n\n```cpp\n\u002F\u002F In constructor:\nAudioComponent = CreateDefaultSubobject\u003CUAudioComponent>(TEXT(\"AudioComponent\"));\nAudioComponent->SetupAttachment(RootComponent);\nAudioComponent->bAutoActivate = false;\nAudioComponent->bStopWhenOwnerDestroyed = true;\n```\n\n### Playback Control\n\n```cpp\nAudioComponent->SetSound(EngineLoopSound);\nAudioComponent->Play(\u002F*StartTime=*\u002F0.0f);\nAudioComponent->Stop();\nAudioComponent->SetPaused(true);\nAudioComponent->FadeIn(0.5f, 1.0f, 0.0f, EAudioFaderCurve::Linear);\nAudioComponent->FadeOut(1.0f, 0.0f, EAudioFaderCurve::Linear);\nAudioComponent->SetVolumeMultiplier(0.5f);\nAudioComponent->SetPitchMultiplier(1.2f);\n\n\u002F\u002F Query play state (EAudioComponentPlayState: Playing, Stopped, Paused, FadingIn, FadingOut)\nEAudioComponentPlayState State = AudioComponent->GetPlayState();\n```\n\n### Delegates (AudioComponent.h)\n\n```cpp\n\u002F\u002F Declared in AudioComponent.h:\n\u002F\u002F DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnAudioFinished)\n\u002F\u002F DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnAudioPlaybackPercent, const USoundWave*, PlayingSoundWave, const float, PlaybackPercent)\n\u002F\u002F DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnAudioPlayStateChanged, EAudioComponentPlayState, PlayState)\n\nAudioComponent->OnAudioFinished.AddDynamic(this, &AMyActor::OnSoundFinished);\nAudioComponent->OnAudioPlaybackPercent.AddDynamic(this, &AMyActor::OnPlaybackPercent);\nAudioComponent->OnAudioPlayStateChanged.AddDynamic(this, &AMyActor::OnPlayStateChanged);\n\n\u002F\u002F Native (non-UObject) binding — no GC overhead:\n\u002F\u002F DECLARE_MULTICAST_DELEGATE_OneParam(FOnAudioFinishedNative, UAudioComponent*)\n\u002F\u002F DECLARE_MULTICAST_DELEGATE_ThreeParams(FOnAudioPlaybackPercentNative, const UAudioComponent*, const USoundWave*, const float)\nAudioComponent->OnAudioFinishedNative.AddUObject(this, &AMyActor::OnSoundFinishedNative);\nAudioComponent->OnAudioPlaybackPercentNative.AddUObject(this, &AMyActor::OnPlaybackPercentNative);\n```\n\n---\n\n## Sound Attenuation (SoundAttenuation.h)\n\nDefined in `USoundAttenuation` assets (wrapping `FSoundAttenuationSettings`).\nAssign via `USoundBase::AttenuationSettings` or pass as override to play functions.\n\n**Attenuation shapes** (`EAttenuationShape`): `Sphere` (default, omnidirectional), `Capsule` (elongated sources), `Box` (room-shaped), `Cone` (directional like spotlights).\n\n**Distance model** (`EAttenuationDistanceModel`): `Linear`, `Logarithmic` (realistic), `NaturalSound` (perception-matched, recommended), `Inverse`, `LogReverse`, `Custom` (curve-driven).\n\n```cpp\n\u002F\u002F Key FSoundAttenuationSettings fields:\nuint8 bAttenuate : 1;          \u002F\u002F enable distance-based volume falloff\nuint8 bSpatialize : 1;         \u002F\u002F enable 3D spatialization\n\u002F\u002F SpatializationAlgorithm: SPATIALIZATION_Default (panning), SPATIALIZATION_HRTF (binaural plugin)\n\nuint8 bAttenuateWithLPF : 1;   \u002F\u002F air absorption (distance-based lowpass)\nfloat LPFRadiusMin;            \u002F\u002F LPF starts at this distance (cm)\nfloat LPFRadiusMax;            \u002F\u002F LPF fully applied at this distance\nfloat LPFFrequencyAtMin;       \u002F\u002F Hz at min distance (e.g. 20000.f = bypass)\nfloat LPFFrequencyAtMax;       \u002F\u002F Hz at max distance (e.g. 800.f = muffled)\n\nuint8 bEnableListenerFocus : 1;\nfloat FocusAzimuth;            \u002F\u002F in-focus cone half-angle (degrees)\nfloat NonFocusAzimuth;         \u002F\u002F non-focus cone half-angle (degrees)\nfloat FocusDistanceScale;      \u002F\u002F \u003C 1.0 makes focused sound seem closer\nfloat NonFocusVolumeAttenuation;\n\nuint8 bEnableOcclusion : 1;\nTEnumAsByte\u003CECollisionChannel> OcclusionTraceChannel; \u002F\u002F e.g. ECC_Visibility\nfloat OcclusionLowPassFilterFrequency;  \u002F\u002F Hz when fully occluded\nfloat OcclusionVolumeAttenuation;       \u002F\u002F 0..1 volume scale when occluded\nfloat OcclusionInterpolationTime;       \u002F\u002F seconds to interpolate\n\nuint8 bEnableReverbSend : 1;\nEReverbSendMethod ReverbSendMethod;     \u002F\u002F Linear, CustomCurve, Manual\nfloat ReverbWetLevelMin;\nfloat ReverbWetLevelMax;\nfloat ReverbDistanceMin;\nfloat ReverbDistanceMax;\n\nuint8 bEnablePriorityAttenuation : 1;  \u002F\u002F reduce priority of distant sounds\nfloat PriorityAttenuationMin;\nfloat PriorityAttenuationMax;\n\n\u002F\u002F Override attenuation inline on a UAudioComponent:\nAudioComponent->bOverrideAttenuation = true;\nAudioComponent->AttenuationOverrides.bAttenuate = true;\nAudioComponent->AttenuationOverrides.bSpatialize = true;\nAudioComponent->AttenuationOverrides.FalloffDistance = 3000.f;\n```\n\n### Audio LOD\n\nDistant sounds can skip processing. Use `bAttenuateWithLPF = true` with `LPFRadiusMin`\u002F`LPFRadiusMax`\nto low-pass-filter far sounds before full attenuation drops them. Set `bEnableSendToAudioLink = false`\nfor background ambience that does not need external routing. `USoundBase::Priority` (0.0–100.0, default 1.0, higher =\nmore important) determines which voices survive when hitting the max channel count set in Audio Settings.\n\n---\n\n## Concurrency (SoundConcurrency.h)\n\n`USoundConcurrency` controls simultaneous voice count. Assign via\n`USoundBase::ConcurrencySet` (`TSet\u003CUSoundConcurrency*>`) or `ConcurrencyOverrides`\n(inline `FSoundConcurrencySettings` when `bOverrideConcurrency = true`).\n\n```cpp\n\u002F\u002F FSoundConcurrencySettings key fields:\nint32 MaxCount;               \u002F\u002F max simultaneous voices in this group\n\u002F\u002F USoundBase::Priority (0.0–100.0, default 1.0) determines which voices survive at MaxCount\nuint8 bLimitToOwner : 1;      \u002F\u002F limit per owning actor if true\nTEnumAsByte\u003CEMaxConcurrentResolutionRule::Type> ResolutionRule;\n\u002F\u002F PreventNew | StopOldest | StopFarthestThenPreventNew | StopFarthestThenOldest\n\u002F\u002F StopLowestPriority | StopQuietest | StopLowestPriorityThenPreventNew\nfloat RetriggerTime;          \u002F\u002F minimum seconds between plays in this group\nfloat VoiceStealReleaseTime;  \u002F\u002F fade duration (s) for evicted sounds\nEConcurrencyVolumeScaleMode VolumeScaleMode; \u002F\u002F Default | Distance | Priority\nfloat VolumeScaleAttackTime;\nfloat VolumeScaleReleaseTime;\n```\n\n---\n\n## Submixes and Sound Classes (SoundSubmix.h)\n\n```\nUSoundSubmixBase (abstract)\n  USoundSubmixWithParentBase\n    USoundSubmix           \u002F\u002F standard submix with effects chain\n    USoundfieldSubmix      \u002F\u002F ambisonics \u002F soundfield\n  UEndpointSubmix          \u002F\u002F external endpoint (haptics, extra device)\n```\n\nTypical tree: Master > {Music, SFX, Voice, Ambient}. Music submix uses `bMuteWhenBackgrounded = true`.\n\n```cpp\n\u002F\u002F Runtime volume control:\nMusicSubmix->SetSubmixOutputVolume(this, 0.5f);  \u002F\u002F linear gain multiplier\nMusicSubmix->SetSubmixWetLevel(this, 1.0f);\nMusicSubmix->SetSubmixDryLevel(this, 0.0f);\n\n\u002F\u002F Dynamic parenting:\nMyChildSubmix->DynamicConnect(this, MasterSubmix);\nMyChildSubmix->DynamicDisconnect(this);\n```\n\n`USoundSubmix::SubmixEffectChain` holds `USoundEffectSubmixPreset` assets\n(reverb `USubmixEffectReverbPreset`, EQ `USubmixEffectEQPreset`, dynamics).\n\n### Submix Effect Chain\n\n```cpp\n\u002F\u002F Add reverb to a submix at runtime\nUSoundSubmix* ReverbSubmix = LoadObject\u003CUSoundSubmix>(nullptr,\n    TEXT(\"\u002FGame\u002FAudio\u002FSubmixes\u002FReverbSubmix\"));\nUSubmixEffectReverbPreset* Preset = NewObject\u003CUSubmixEffectReverbPreset>();\nPreset->Settings.Density = 0.85f;\nPreset->Settings.Diffusion = 0.8f;\nPreset->Settings.DecayTime = 2.5f;\nReverbSubmix->SubmixEffectChain.Add(Preset);\n```\n\n**Sound classes** define volume\u002Fpitch hierarchy parallel to submixes. Assign via `USoundBase::SoundClassObject`.\n\n```cpp\n\u002F\u002F Sound Mix modifiers — layer temporary volume\u002Fpitch adjustments by sound class:\nUGameplayStatics::SetBaseSoundMix(this, DefaultMix);            \u002F\u002F set the base mix (usually once)\nUGameplayStatics::PushSoundMixModifier(this, CombatMix);        \u002F\u002F push a modifier (stacks)\n\u002F\u002F ... later, when leaving combat:\nUGameplayStatics::PopSoundMixModifier(this, CombatMix);         \u002F\u002F remove the modifier layer\n\u002F\u002F ClearSoundMixModifiers removes all pushed modifiers at once\nUGameplayStatics::ClearSoundMixModifiers(this);\n```\n\n`USoundMix` assets define per-`USoundClass` volume and pitch adjustments. Push\u002Fpop lets you layer context-dependent audio profiles (combat, stealth, underwater) without manual volume bookkeeping.\n\n---\n\n## MetaSounds\n\n`UMetaSoundSource` derives from `USoundBase` — plays anywhere a `USoundBase` is accepted.\n\n```cpp\n\u002F\u002F UAudioComponent implements ISoundParameterControllerInterface:\nMetaComp->SetFloatParameter(FName(\"Pitch\"), 1.5f);\nMetaComp->SetBoolParameter(FName(\"IsUnderwater\"), true);\nMetaComp->SetIntParameter(FName(\"SurfaceType\"), 2);\nMetaComp->SetTriggerParameter(FName(\"OnImpact\"));  \u002F\u002F impulse trigger input\nMetaComp->ResetParameters();\n```\n\n| Criterion | SoundCue | MetaSound |\n|---|---|---|\n| Runtime parameters | Limited (wave params) | Typed inputs, full parameter system |\n| Procedural audio | No | Yes (oscillators, noise, DSP filters) |\n| Reactive to gameplay | Via parameter nodes | Native — bind any float\u002Fbool\u002Ftrigger |\n| Use when | Randomized pre-authored sounds | Adaptive music, procedural SFX, state-driven audio |\n\n---\n\n## Submix Spectrum Analysis and Envelope Following (SoundSubmix.h)\n\n```cpp\n\u002F\u002F Envelope following:\nSFXSubmix->StartEnvelopeFollowing(this);\nFOnSubmixEnvelopeBP Env;\nEnv.BindDynamic(this, &AMyActor::OnSubmixEnvelope);\nSFXSubmix->AddEnvelopeFollowerDelegate(this, Env);\nSFXSubmix->StopEnvelopeFollowing(this);\n\u002F\u002F Callback: void OnSubmixEnvelope(const TArray\u003Cfloat>& Envelope);\n\n\u002F\u002F Spectrum analysis:\nSFXSubmix->StartSpectralAnalysis(this,\n    EFFTSize::Medium, EFFTPeakInterpolationMethod::Linear,\n    EFFTWindowType::Hann, 0.0f, EAudioSpectrumType::MagnitudeSpectrum\n);\n\nTArray\u003CFSoundSubmixSpectralAnalysisBandSettings> Bands;\nFSoundSubmixSpectralAnalysisBandSettings LowBand;\nLowBand.BandFrequency = 80.f; LowBand.AttackTimeMsec = 10.f; LowBand.ReleaseTimeMsec = 100.f;\nBands.Add(LowBand);\n\nFOnSubmixSpectralAnalysisBP Spectral;\nSpectral.BindDynamic(this, &AMyActor::OnSpectralAnalysis);\nSFXSubmix->AddSpectralAnalysisDelegate(\n    this, Bands, Spectral,\n    30.f \u002F*UpdateRateHz*\u002F, -40.f \u002F*DecibelFloor*\u002F, true \u002F*Normalize*\u002F, false \u002F*AutoRange*\u002F\n);\nSFXSubmix->StopSpectralAnalysis(this);\n\u002F\u002F Callback: void OnSpectralAnalysis(const TArray\u003Cfloat>& Magnitudes);\n```\n\n---\n\n## Module Dependencies\n\n```csharp\n\u002F\u002F In .Build.cs:\nPublicDependencyModuleNames.AddRange(new string[] { \"Engine\", \"AudioMixer\" });\nPublicDependencyModuleNames.Add(\"MetasoundEngine\");    \u002F\u002F for MetaSound parameters\nPublicDependencyModuleNames.Add(\"MetasoundFrontend\");\n```\n\n```cpp\n#include \"Components\u002FAudioComponent.h\"\n#include \"Kismet\u002FGameplayStatics.h\"\n#include \"Sound\u002FSoundBase.h\"\n#include \"Sound\u002FSoundCue.h\"\n#include \"Sound\u002FSoundWave.h\"\n#include \"Sound\u002FSoundAttenuation.h\"\n#include \"Sound\u002FSoundConcurrency.h\"\n#include \"Sound\u002FSoundSubmix.h\"\n```\n\n---\n\n## Audio Analysis\n\n### Submix Spectrum and Envelope\n\nSee the existing submix analysis section above for real-time analysis via `USoundSubmix`.\n\n### Non-Real-Time Analysis (NRT)\n\n`UAudioAnalyzerNRT` is the abstract base class for offline analyzers. `ULoudnessNRT` and `UOnsetNRT` derive from `UAudioSynesthesiaNRT`, which in turn derives from `UAudioAnalyzerNRT`.\n\nFor offline audio analysis (e.g., beat detection for rhythmic gameplay), use the Audio Synesthesia plugin:\n\n```cpp\n\u002F\u002F Build.cs: \"AudioSynesthesia\"\n#include \"AudioSynesthesiaModule.h\"\n\n\u002F\u002F Create an analyzer — LoudnessNRT analyzes an entire sound asset offline\nULoudnessNRT* Analyzer = NewObject\u003CULoudnessNRT>();\nULoudnessNRTSettings* Settings = NewObject\u003CULoudnessNRTSettings>();\nSettings->AnalysisPeriod = 0.01f; \u002F\u002F 10ms windows\n\nAnalyzer->Settings = Settings;\nAnalyzer->Sound = MySoundWave;\nAnalyzer->AnalyzeAudio();  \u002F\u002F WITH_EDITOR only; call from editor utility or cook-time code\n\n\u002F\u002F Query results at specific timestamps\nfloat Loudness;\nAnalyzer->GetLoudnessAtTime(1.5f, Loudness);\n\n\u002F\u002F For beat detection, use OnsetNRT:\nUOnsetNRT* OnsetAnalyzer = NewObject\u003CUOnsetNRT>();\nOnsetAnalyzer->Sound = MySoundWave;\nOnsetAnalyzer->AnalyzeAudio();  \u002F\u002F WITH_EDITOR only\nTArray\u003Cfloat> OnsetTimestamps;\nTArray\u003Cfloat> OnsetStrengths;\nOnsetAnalyzer->GetNormalizedChannelOnsetsBetweenTimes(\n    0.f, Duration, 0, OnsetTimestamps, OnsetStrengths);\n```\n\n**Why NRT**: Pre-analyze tracks to generate beat maps, loudness curves, or onset markers. Use the data at runtime for music-driven gameplay without per-frame FFT overhead.\n\n---\n\n## Common Mistakes and Anti-Patterns\n\n**Spawning a new AudioComponent every fire event**\n```cpp\n\u002F\u002F WRONG — leaks a component instance per call\nUAudioComponent* Comp = NewObject\u003CUAudioComponent>(this);\nComp->SetSound(FireSound); Comp->Play();\n\n\u002F\u002F CORRECT — fire-and-forget for one-shots\nUGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation());\n\u002F\u002F CORRECT — cache a single component for repeated\u002Flooping sounds\nif (!CachedFireAudio) { CachedFireAudio = UGameplayStatics::SpawnSoundAttached(..., \u002F*bAutoDestroy=*\u002Ffalse); }\nCachedFireAudio->Play();\n```\n\n**Playing 3D sounds without attenuation**\n```cpp\n\u002F\u002F WRONG — full volume at any distance\nUGameplayStatics::PlaySoundAtLocation(this, FootstepSound, Location);\n\u002F\u002F CORRECT — pass or assign USoundAttenuation with sphere falloff tuned to gameplay scale\n```\n\n**Ignoring concurrency on high-frequency sounds**\n```cpp\n\u002F\u002F WRONG — 20 simultaneous explosions with default concurrency\nUGameplayStatics::PlaySoundAtLocation(this, ExplosionSound, Location);\n\u002F\u002F CORRECT — pass USoundConcurrency: MaxCount=4, ResolutionRule=StopFarthestThenOldest\n```\n\n**Playing audio on a dedicated server**\n```cpp\n\u002F\u002F WRONG — FAudioDevice not initialized on server, causes crash\u002Flog spam\nvoid AWeapon::Fire() { UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation()); }\n\u002F\u002F CORRECT\nvoid AWeapon::Fire() {\n    if (GetNetMode() != NM_DedicatedServer) {\n        UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation());\n    }\n}\n```\n\n**Forgetting to unbind delegates before destruction**\n```cpp\n\u002F\u002F In EndPlay:\nif (AudioComponent) { AudioComponent->OnAudioFinished.RemoveAll(this); AudioComponent->Stop(); }\n```\n\n**Using PlaySound2D for in-world sounds**\n```cpp\n\u002F\u002F WRONG — no attenuation or spatialization\nUGameplayStatics::PlaySound2D(this, GunShot);\n\u002F\u002F CORRECT\nUGameplayStatics::PlaySoundAtLocation(this, GunShot, GetActorLocation());\n```\n\n---\n\n## Platform and Edge Case Considerations\n\n- **Mobile** — 16–32 voice limit. Use aggressive concurrency. Prefer resident loading for SFX. Disable HRTF unless the platform supports it.\n- **Dedicated servers** — Guard all audio calls with `GetNetMode() != NM_DedicatedServer`.\n- **Streaming audio** — Set `LoadingBehavior = LoadOnDemand` on long music SoundWave assets. Never load minutes of music resident.\n- **App focus loss** — Set `bMuteWhenBackgrounded = true` on music\u002FSFX submixes. For custom handling:\n\n### Focus Loss Handling\n\n```cpp\n\u002F\u002F In your GameInstance or AudioManager\nFCoreDelegates::ApplicationWillDeactivateDelegate.AddUObject(\n    this, &UMyAudioManager::OnAppDeactivate);\n\nvoid UMyAudioManager::OnAppDeactivate()\n{\n    FAudioDeviceHandle Device = GEngine->GetMainAudioDevice();\n    if (Device.IsValid()) { Device->SetTransientPrimaryVolume(0.f); }\n}\n```\n\n- **VR** — Enable `bSpatialize = true` and `SpatializationAlgorithm = SPATIALIZATION_HRTF` on all 3D attenuation assets.\n- **Audio LOD** — Use `bEnablePriorityAttenuation` to reduce priority of distant sounds before voice-budget culling.\n\n---\n\n## Related Skills\n\n- `ue-actor-component-architecture` — UAudioComponent lifetime, attachment, and replication patterns\n- `ue-niagara-effects` — synchronizing audio events with particle system callbacks\n- `ue-cpp-foundations` — delegate binding patterns, UPROPERTY and UFUNCTION macros\n",{},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Fquodsoler\u002Funreal-engine-skills\u002Fue-audio-system",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":7,"skillName":5,"commands":40,"prompt":50,"zipAvailable":51},[41,44,47],{"tool":42,"command":43},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill ue-audio-system",{"tool":45,"command":46},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill ue-audio-system",{"tool":48,"command":49},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill ue-audio-system","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fquodsoler\u002Funreal-engine-skills\u002Fue-audio-system\u002FSKILL.md",true,[],[54,66,76,85,91,98],{"skillNo":55,"name":56,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":57,"categories":58,"keywords":62,"publishedAt":26},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[59],{"categoryNo":60,"categoryName":61,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[63,64,65],"model","model hierarchy","model hierarchy skill",{"skillNo":67,"name":68,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":69,"categories":70,"keywords":72,"publishedAt":26},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[71],{"categoryNo":60,"categoryName":61,"taxonomyType":20,"taxonomyTypeDesc":21},[73,74,75],"MCP","zoom","zoom mcp",{"skillNo":77,"name":78,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":79,"categories":80,"keywords":81,"publishedAt":26},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[82,83,84,74],"sdk","zoom apps sdk","apps",{"skillNo":86,"name":87,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":88,"categories":89,"keywords":90,"publishedAt":26},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[87],{"skillNo":92,"name":93,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":94,"categories":95,"keywords":97,"publishedAt":26},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[96],{"categoryNo":60,"categoryName":61,"taxonomyType":20,"taxonomyTypeDesc":21},[93],{"skillNo":99,"name":100,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":101,"categories":102,"keywords":103,"publishedAt":26},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[100]]