ue-audio-system
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseUE Audio System
UE 音频系统
You are an expert in Unreal Engine's audio systems, covering UAudioComponent, sound asset types,
spatial attenuation, concurrency management, submix routing, MetaSounds, and runtime audio analysis.
你是Unreal Engine音频系统方面的专家,涵盖UAudioComponent、声音资源类型、空间衰减、并发管理、子混音路由、MetaSounds和运行时音频分析。
Context Check
上下文检查
Before implementing audio, read for:
.agents/ue-project-context.md- Audio plugins enabled (Resonance Audio, Steam Audio, Wwise, FMOD, MetaSound plugin version)
- Target platforms — mobile has strict voice limits; consoles differ from PC
- Dedicated server flag — audio must be skipped server-side or it will crash/log errors
- VR flag — VR projects require binaural spatialization settings
在实现音频之前,请阅读获取以下信息:
.agents/ue-project-context.md- 已启用的音频插件(Resonance Audio、Steam Audio、Wwise、FMOD、MetaSound插件版本)
- 目标平台——移动平台有严格的声道限制;主机平台与PC平台存在差异
- 专用服务器标记——服务器端必须跳过音频处理,否则会崩溃或产生日志错误
- VR标记——VR项目需要双耳空间化设置
Information Gathering
信息收集
Ask about:
- One-shot SFX, looping ambient, music, UI feedback, or dialogue?
- Spatialized (follows actor) or global 2D?
- Concurrency concern (gunshots, footsteps, explosions)?
- Runtime control needed (fade, pause, parameter changes)?
- MetaSound procedural or pre-authored SoundCue/SoundWave?
请询问以下内容:
- 是一次性SFX、循环环境音、音乐、UI反馈音还是对话音?
- 是空间化(跟随Actor)还是全局2D音频?
- 是否存在并发问题(如枪声、脚步声、爆炸声)?
- 是否需要运行时控制(淡入淡出、暂停、参数更改)?
- 是使用MetaSound程序化音频还是预制作的SoundCue/SoundWave?
Sound Asset Hierarchy
声音资源层级
USoundBase // abstract base (SoundBase.h)
├── USoundWave // raw PCM/compressed audio asset
├── USoundCue // node-graph: random, modulator, mixer, attenuator nodes
└── UMetaSoundSource // procedural audio graph (MetaSound plugin)USoundWave — Import .wav/.ogg/.flac. Set and on asset.
SoundClassObjectAttenuationSettingsUSoundCue — Node graph combining multiple waves. Key nodes:
, , , ,
, , .
USoundNodeRandomUSoundNodeModulatorUSoundNodeMixerUSoundNodeAttenuationUSoundNodeLoopingUSoundNodeDelayUSoundNodeDistanceCrossFadeUMetaSoundSource — Procedural audio graph. Declare typed inputs (float, bool, int32, trigger).
Set parameters at runtime via , , .
UAudioComponent::SetFloatParameterSetBoolParameterSetIntParameterUSoundBase // 抽象基类(SoundBase.h)
├── USoundWave // 原始PCM/压缩音频资源
├── USoundCue // 节点图:随机、调制器、混音器、衰减器节点
└── UMetaSoundSource // 程序化音频图(MetaSound插件)USoundWave — 导入.wav/.ogg/.flac格式文件。在资源上设置和。
SoundClassObjectAttenuationSettingsUSoundCue — 组合多个音频波形的节点图。关键节点:
、、、、
、、。
USoundNodeRandomUSoundNodeModulatorUSoundNodeMixerUSoundNodeAttenuationUSoundNodeLoopingUSoundNodeDelayUSoundNodeDistanceCrossFadeUMetaSoundSource — 程序化音频图。声明类型化输入(float、bool、int32、trigger)。
通过、、在运行时设置参数。
UAudioComponent::SetFloatParameterSetBoolParameterSetIntParameterStreaming Long Audio
长音频流处理
For music and ambient tracks exceeding ~30 seconds, set :
for short SFX, for music loaded at level start.
Long files should use to avoid loading the full waveform into memory.
In the editor: SoundWave asset → Details → Loading → Loading Behavior.
USoundWave::LoadingBehaviorESoundWaveLoadingBehavior::ForceInlineRetainOnLoadLoadOnDemand对于时长超过约30秒的音乐和环境音轨,设置:
短SFX使用,关卡启动时加载的音乐使用。
长文件应使用,避免将完整波形加载到内存中。
在编辑器中操作:SoundWave资源 → 详情 → 加载 → 加载行为。
USoundWave::LoadingBehaviorESoundWaveLoadingBehavior::ForceInlineRetainOnLoadLoadOnDemandPlaying Sounds from C++
使用C++播放声音
Fire-and-Forget
一次性播放(无需后续控制)
cpp
#include "Kismet/GameplayStatics.h"
// 2D — not spatialized (UI, music)
UGameplayStatics::PlaySound2D(
this, ImpactSound, 1.0f /*Vol*/, 1.0f /*Pitch*/, 0.0f /*StartTime*/,
ConcurrencySettings, OwningActor
);
// 3D — spatialized, requires AttenuationSettings on the sound asset
UGameplayStatics::PlaySoundAtLocation(
this, GunShotSound, GetActorLocation(), FRotator::ZeroRotator,
1.0f, 1.0f, 0.0f,
AttenuationOverride, // USoundAttenuation* (nullptr = use asset default)
ConcurrencyOverride, // USoundConcurrency* (nullptr = use asset default)
this // OwningActor for per-owner concurrency
);cpp
#include "Kismet/GameplayStatics.h"
// 2D音频 — 无空间化(UI、音乐)
UGameplayStatics::PlaySound2D(
this, ImpactSound, 1.0f /*音量*/, 1.0f /*音调*/, 0.0f /*开始时间*/,
ConcurrencySettings, OwningActor
);
// 3D音频 — 空间化,要求声音资源上设置AttenuationSettings
UGameplayStatics::PlaySoundAtLocation(
this, GunShotSound, GetActorLocation(), FRotator::ZeroRotator,
1.0f, 1.0f, 0.0f,
AttenuationOverride, // USoundAttenuation*(nullptr表示使用资源默认设置)
ConcurrencyOverride, // USoundConcurrency*(nullptr表示使用资源默认设置)
this // 用于按所有者控制并发的OwningActor
);Spawn with Handle
生成带控制句柄的音频
cpp
// Returns UAudioComponent* — auto-destroyed when sound finishes if bAutoDestroy=true
UAudioComponent* Comp = UGameplayStatics::SpawnSoundAtLocation(
this, ExplosionSound, Location, FRotator::ZeroRotator,
1.0f, 1.0f, 0.0f, AttenuationSettings, nullptr, /*bAutoDestroy=*/true
);
// Attach to a moving component (vehicle engine)
UAudioComponent* EngineAudio = UGameplayStatics::SpawnSoundAttached(
EngineLoopSound, GetMesh(), NAME_None,
FVector::ZeroVector, FRotator::ZeroRotator,
EAttachLocation::SnapToTargetIncludingScale,
/*bStopWhenAttachedToDestroyed=*/true,
1.0f, 1.0f, 0.0f, AttenuationSettings, nullptr,
/*bAutoDestroy=*/false // keep alive for looping
);cpp
// 返回UAudioComponent* — 如果bAutoDestroy=true,声音结束时会自动销毁
UAudioComponent* Comp = UGameplayStatics::SpawnSoundAtLocation(
this, ExplosionSound, Location, FRotator::ZeroRotator,
1.0f, 1.0f, 0.0f, AttenuationSettings, nullptr, /*bAutoDestroy=*/true
);
// 附加到移动组件(如车辆引擎)
UAudioComponent* EngineAudio = UGameplayStatics::SpawnSoundAttached(
EngineLoopSound, GetMesh(), NAME_None,
FVector::ZeroVector, FRotator::ZeroRotator,
EAttachLocation::SnapToTargetIncludingScale,
/*bStopWhenAttachedToDestroyed=*/true,
1.0f, 1.0f, 0.0f, AttenuationSettings, nullptr,
/*bAutoDestroy=*/false // 保持存活以实现循环播放
);UAudioComponent as Permanent Actor Component
将UAudioComponent作为永久Actor组件
cpp
// In constructor:
AudioComponent = CreateDefaultSubobject<UAudioComponent>(TEXT("AudioComponent"));
AudioComponent->SetupAttachment(RootComponent);
AudioComponent->bAutoActivate = false;
AudioComponent->bStopWhenOwnerDestroyed = true;cpp
// 在构造函数中:
AudioComponent = CreateDefaultSubobject<UAudioComponent>(TEXT("AudioComponent"));
AudioComponent->SetupAttachment(RootComponent);
AudioComponent->bAutoActivate = false;
AudioComponent->bStopWhenOwnerDestroyed = true;Playback Control
播放控制
cpp
AudioComponent->SetSound(EngineLoopSound);
AudioComponent->Play(/*StartTime=*/0.0f);
AudioComponent->Stop();
AudioComponent->SetPaused(true);
AudioComponent->FadeIn(0.5f, 1.0f, 0.0f, EAudioFaderCurve::Linear);
AudioComponent->FadeOut(1.0f, 0.0f, EAudioFaderCurve::Linear);
AudioComponent->SetVolumeMultiplier(0.5f);
AudioComponent->SetPitchMultiplier(1.2f);
// Query play state (EAudioComponentPlayState: Playing, Stopped, Paused, FadingIn, FadingOut)
EAudioComponentPlayState State = AudioComponent->GetPlayState();cpp
AudioComponent->SetSound(EngineLoopSound);
AudioComponent->Play(/*StartTime=*/0.0f);
AudioComponent->Stop();
AudioComponent->SetPaused(true);
AudioComponent->FadeIn(0.5f, 1.0f, 0.0f, EAudioFaderCurve::Linear);
AudioComponent->FadeOut(1.0f, 0.0f, EAudioFaderCurve::Linear);
AudioComponent->SetVolumeMultiplier(0.5f);
AudioComponent->SetPitchMultiplier(1.2f);
// 查询播放状态(EAudioComponentPlayState:Playing、Stopped、Paused、FadingIn、FadingOut)
EAudioComponentPlayState State = AudioComponent->GetPlayState();Delegates (AudioComponent.h)
委托(AudioComponent.h)
cpp
// Declared in AudioComponent.h:
// DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnAudioFinished)
// DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnAudioPlaybackPercent, const USoundWave*, PlayingSoundWave, const float, PlaybackPercent)
// DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnAudioPlayStateChanged, EAudioComponentPlayState, PlayState)
AudioComponent->OnAudioFinished.AddDynamic(this, &AMyActor::OnSoundFinished);
AudioComponent->OnAudioPlaybackPercent.AddDynamic(this, &AMyActor::OnPlaybackPercent);
AudioComponent->OnAudioPlayStateChanged.AddDynamic(this, &AMyActor::OnPlayStateChanged);
// Native (non-UObject) binding — no GC overhead:
// DECLARE_MULTICAST_DELEGATE_OneParam(FOnAudioFinishedNative, UAudioComponent*)
// DECLARE_MULTICAST_DELEGATE_ThreeParams(FOnAudioPlaybackPercentNative, const UAudioComponent*, const USoundWave*, const float)
AudioComponent->OnAudioFinishedNative.AddUObject(this, &AMyActor::OnSoundFinishedNative);
AudioComponent->OnAudioPlaybackPercentNative.AddUObject(this, &AMyActor::OnPlaybackPercentNative);cpp
// 在AudioComponent.h中声明:
// DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnAudioFinished)
// DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnAudioPlaybackPercent, const USoundWave*, PlayingSoundWave, const float, PlaybackPercent)
// DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnAudioPlayStateChanged, EAudioComponentPlayState, PlayState)
AudioComponent->OnAudioFinished.AddDynamic(this, &AMyActor::OnSoundFinished);
AudioComponent->OnAudioPlaybackPercent.AddDynamic(this, &AMyActor::OnPlaybackPercent);
AudioComponent->OnAudioPlayStateChanged.AddDynamic(this, &AMyActor::OnPlayStateChanged);
// 原生(非UObject)绑定 — 无GC开销:
// DECLARE_MULTICAST_DELEGATE_OneParam(FOnAudioFinishedNative, UAudioComponent*)
// DECLARE_MULTICAST_DELEGATE_ThreeParams(FOnAudioPlaybackPercentNative, const UAudioComponent*, const USoundWave*, const float)
AudioComponent->OnAudioFinishedNative.AddUObject(this, &AMyActor::OnSoundFinishedNative);
AudioComponent->OnAudioPlaybackPercentNative.AddUObject(this, &AMyActor::OnPlaybackPercentNative);Sound Attenuation (SoundAttenuation.h)
声音衰减(SoundAttenuation.h)
Defined in assets (wrapping ).
Assign via or pass as override to play functions.
USoundAttenuationFSoundAttenuationSettingsUSoundBase::AttenuationSettingsAttenuation shapes (): (default, omnidirectional), (elongated sources), (room-shaped), (directional like spotlights).
EAttenuationShapeSphereCapsuleBoxConeDistance model (): , (realistic), (perception-matched, recommended), , , (curve-driven).
EAttenuationDistanceModelLinearLogarithmicNaturalSoundInverseLogReverseCustomcpp
// Key FSoundAttenuationSettings fields:
uint8 bAttenuate : 1; // enable distance-based volume falloff
uint8 bSpatialize : 1; // enable 3D spatialization
// SpatializationAlgorithm: SPATIALIZATION_Default (panning), SPATIALIZATION_HRTF (binaural plugin)
uint8 bAttenuateWithLPF : 1; // air absorption (distance-based lowpass)
float LPFRadiusMin; // LPF starts at this distance (cm)
float LPFRadiusMax; // LPF fully applied at this distance
float LPFFrequencyAtMin; // Hz at min distance (e.g. 20000.f = bypass)
float LPFFrequencyAtMax; // Hz at max distance (e.g. 800.f = muffled)
uint8 bEnableListenerFocus : 1;
float FocusAzimuth; // in-focus cone half-angle (degrees)
float NonFocusAzimuth; // non-focus cone half-angle (degrees)
float FocusDistanceScale; // < 1.0 makes focused sound seem closer
float NonFocusVolumeAttenuation;
uint8 bEnableOcclusion : 1;
TEnumAsByte<ECollisionChannel> OcclusionTraceChannel; // e.g. ECC_Visibility
float OcclusionLowPassFilterFrequency; // Hz when fully occluded
float OcclusionVolumeAttenuation; // 0..1 volume scale when occluded
float OcclusionInterpolationTime; // seconds to interpolate
uint8 bEnableReverbSend : 1;
EReverbSendMethod ReverbSendMethod; // Linear, CustomCurve, Manual
float ReverbWetLevelMin;
float ReverbWetLevelMax;
float ReverbDistanceMin;
float ReverbDistanceMax;
uint8 bEnablePriorityAttenuation : 1; // reduce priority of distant sounds
float PriorityAttenuationMin;
float PriorityAttenuationMax;
// Override attenuation inline on a UAudioComponent:
AudioComponent->bOverrideAttenuation = true;
AudioComponent->AttenuationOverrides.bAttenuate = true;
AudioComponent->AttenuationOverrides.bSpatialize = true;
AudioComponent->AttenuationOverrides.FalloffDistance = 3000.f;定义于资源中(封装)。
通过分配,或作为覆盖参数传递给播放函数。
USoundAttenuationFSoundAttenuationSettingsUSoundBase::AttenuationSettings衰减形状():(默认,全向)、(长条状声源)、(房间形状)、(类似聚光灯的定向)。
EAttenuationShapeSphereCapsuleBoxCone距离模型():、(真实感)、(匹配听觉感知,推荐)、、、(曲线驱动)。
EAttenuationDistanceModelLinearLogarithmicNaturalSoundInverseLogReverseCustomcpp
// FSoundAttenuationSettings关键字段:
uint8 bAttenuate : 1; // 启用基于距离的音量衰减
uint8 bSpatialize : 1; // 启用3D空间化
// SpatializationAlgorithm: SPATIALIZATION_Default(声像定位)、SPATIALIZATION_HRTF(双耳插件)
uint8 bAttenuateWithLPF : 1; // 空气吸收(基于距离的低通滤波)
float LPFRadiusMin; // LPF开始生效的距离(厘米)
float LPFRadiusMax; // LPF完全生效的距离
float LPFFrequencyAtMin; // 最小距离时的频率(例如20000.f = 不生效)
float LPFFrequencyAtMax; // 最大距离时的频率(例如800.f = 模糊效果)
uint8 bEnableListenerFocus : 1;
float FocusAzimuth; // 聚焦锥半角(度)
float NonFocusAzimuth; // 非聚焦锥半角(度)
float FocusDistanceScale; // <1.0会让聚焦的声音听起来更近
float NonFocusVolumeAttenuation;
uint8 bEnableOcclusion : 1;
TEnumAsByte<ECollisionChannel> OcclusionTraceChannel; // 例如ECC_Visibility
float OcclusionLowPassFilterFrequency; // 完全遮挡时的频率(Hz)
float OcclusionVolumeAttenuation; // 遮挡时的音量缩放(0..1)
float OcclusionInterpolationTime; // 插值时间(秒)
uint8 bEnableReverbSend : 1;
EReverbSendMethod ReverbSendMethod; // Linear、CustomCurve、Manual
float ReverbWetLevelMin;
float ReverbWetLevelMax;
float ReverbDistanceMin;
float ReverbDistanceMax;
uint8 bEnablePriorityAttenuation : 1; // 降低远处声音的优先级
float PriorityAttenuationMin;
float PriorityAttenuationMax;
// 在UAudioComponent上内联覆盖衰减设置:
AudioComponent->bOverrideAttenuation = true;
AudioComponent->AttenuationOverrides.bAttenuate = true;
AudioComponent->AttenuationOverrides.bSpatialize = true;
AudioComponent->AttenuationOverrides.FalloffDistance = 3000.f;Audio LOD
音频LOD
Distant sounds can skip processing. Use with /
to low-pass-filter far sounds before full attenuation drops them. Set
for background ambience that does not need external routing. (0.0–100.0, default 1.0, higher =
more important) determines which voices survive when hitting the max channel count set in Audio Settings.
bAttenuateWithLPF = trueLPFRadiusMinLPFRadiusMaxbEnableSendToAudioLink = falseUSoundBase::Priority远处的声音可以跳过处理。使用并设置/,在完全衰减前对远处声音应用低通滤波。对于不需要外部路由的背景环境音,设置。(0.0–100.0,默认1.0,值越高越重要)决定了当达到音频设置中的最大声道数时,哪些声道会被保留。
bAttenuateWithLPF = trueLPFRadiusMinLPFRadiusMaxbEnableSendToAudioLink = falseUSoundBase::PriorityConcurrency (SoundConcurrency.h)
并发控制(SoundConcurrency.h)
USoundConcurrencyUSoundBase::ConcurrencySetTSet<USoundConcurrency*>ConcurrencyOverridesFSoundConcurrencySettingsbOverrideConcurrency = truecpp
// FSoundConcurrencySettings key fields:
int32 MaxCount; // max simultaneous voices in this group
// USoundBase::Priority (0.0–100.0, default 1.0) determines which voices survive at MaxCount
uint8 bLimitToOwner : 1; // limit per owning actor if true
TEnumAsByte<EMaxConcurrentResolutionRule::Type> ResolutionRule;
// PreventNew | StopOldest | StopFarthestThenPreventNew | StopFarthestThenOldest
// StopLowestPriority | StopQuietest | StopLowestPriorityThenPreventNew
float RetriggerTime; // minimum seconds between plays in this group
float VoiceStealReleaseTime; // fade duration (s) for evicted sounds
EConcurrencyVolumeScaleMode VolumeScaleMode; // Default | Distance | Priority
float VolumeScaleAttackTime;
float VolumeScaleReleaseTime;USoundConcurrencyUSoundBase::ConcurrencySetTSet<USoundConcurrency*>bOverrideConcurrency = trueFSoundConcurrencySettingsConcurrencyOverridescpp
// FSoundConcurrencySettings关键字段:
int32 MaxCount; // 该组中允许的最大同时声道数
// USoundBase::Priority(0.0–100.0,默认1.0)决定达到MaxCount时保留哪些声道
uint8 bLimitToOwner : 1; // 如果为true,按所属Actor限制并发数
TEnumAsByte<EMaxConcurrentResolutionRule::Type> ResolutionRule;
// PreventNew | StopOldest | StopFarthestThenPreventNew | StopFarthestThenOldest
// StopLowestPriority | StopQuietest | StopLowestPriorityThenPreventNew
float RetriggerTime; // 该组中两次播放的最小间隔(秒)
float VoiceStealReleaseTime; // 被替换声音的淡出时长(秒)
EConcurrencyVolumeScaleMode VolumeScaleMode; // Default | Distance | Priority
float VolumeScaleAttackTime;
float VolumeScaleReleaseTime;Submixes and Sound Classes (SoundSubmix.h)
子混音与声音类(SoundSubmix.h)
USoundSubmixBase (abstract)
USoundSubmixWithParentBase
USoundSubmix // standard submix with effects chain
USoundfieldSubmix // ambisonics / soundfield
UEndpointSubmix // external endpoint (haptics, extra device)Typical tree: Master > {Music, SFX, Voice, Ambient}. Music submix uses .
bMuteWhenBackgrounded = truecpp
// Runtime volume control:
MusicSubmix->SetSubmixOutputVolume(this, 0.5f); // linear gain multiplier
MusicSubmix->SetSubmixWetLevel(this, 1.0f);
MusicSubmix->SetSubmixDryLevel(this, 0.0f);
// Dynamic parenting:
MyChildSubmix->DynamicConnect(this, MasterSubmix);
MyChildSubmix->DynamicDisconnect(this);USoundSubmix::SubmixEffectChainUSoundEffectSubmixPresetUSubmixEffectReverbPresetUSubmixEffectEQPresetUSoundSubmixBase (抽象类)
USoundSubmixWithParentBase
USoundSubmix // 带效果链的标准子混音
USoundfieldSubmix // 环绕声/声场
UEndpointSubmix // 外部端点(触觉反馈、额外设备)典型层级:主混音 > {音乐、SFX、语音、环境音}。音乐子混音使用。
bMuteWhenBackgrounded = truecpp
// 运行时音量控制:
MusicSubmix->SetSubmixOutputVolume(this, 0.5f); // 线性增益乘数
MusicSubmix->SetSubmixWetLevel(this, 1.0f);
MusicSubmix->SetSubmixDryLevel(this, 0.0f);
// 动态父级连接:
MyChildSubmix->DynamicConnect(this, MasterSubmix);
MyChildSubmix->DynamicDisconnect(this);USoundSubmix::SubmixEffectChainUSoundEffectSubmixPresetUSubmixEffectReverbPresetUSubmixEffectEQPresetSubmix Effect Chain
子混音效果链
cpp
// Add reverb to a submix at runtime
USoundSubmix* ReverbSubmix = LoadObject<USoundSubmix>(nullptr,
TEXT("/Game/Audio/Submixes/ReverbSubmix"));
USubmixEffectReverbPreset* Preset = NewObject<USubmixEffectReverbPreset>();
Preset->Settings.Density = 0.85f;
Preset->Settings.Diffusion = 0.8f;
Preset->Settings.DecayTime = 2.5f;
ReverbSubmix->SubmixEffectChain.Add(Preset);Sound classes define volume/pitch hierarchy parallel to submixes. Assign via .
USoundBase::SoundClassObjectcpp
// Sound Mix modifiers — layer temporary volume/pitch adjustments by sound class:
UGameplayStatics::SetBaseSoundMix(this, DefaultMix); // set the base mix (usually once)
UGameplayStatics::PushSoundMixModifier(this, CombatMix); // push a modifier (stacks)
// ... later, when leaving combat:
UGameplayStatics::PopSoundMixModifier(this, CombatMix); // remove the modifier layer
// ClearSoundMixModifiers removes all pushed modifiers at once
UGameplayStatics::ClearSoundMixModifiers(this);USoundMixUSoundClasscpp
// 在运行时为子混音添加混响
USoundSubmix* ReverbSubmix = LoadObject<USoundSubmix>(nullptr,
TEXT("/Game/Audio/Submixes/ReverbSubmix"));
USubmixEffectReverbPreset* Preset = NewObject<USubmixEffectReverbPreset>();
Preset->Settings.Density = 0.85f;
Preset->Settings.Diffusion = 0.8f;
Preset->Settings.DecayTime = 2.5f;
ReverbSubmix->SubmixEffectChain.Add(Preset);声音类定义与子混音平行的音量/音调层级。通过分配。
USoundBase::SoundClassObjectcpp
// 声音混音修改器 — 按声音类分层临时调整音量/音调:
UGameplayStatics::SetBaseSoundMix(this, DefaultMix); // 设置基础混音(通常只调用一次)
UGameplayStatics::PushSoundMixModifier(this, CombatMix); // 添加修改器(可堆叠)
// ... 之后退出战斗时:
UGameplayStatics::PopSoundMixModifier(this, CombatMix); // 移除修改器层
// ClearSoundMixModifiers会一次性移除所有已添加的修改器
UGameplayStatics::ClearSoundMixModifiers(this);USoundMixUSoundClassMetaSounds
MetaSounds
UMetaSoundSourceUSoundBaseUSoundBasecpp
// UAudioComponent implements ISoundParameterControllerInterface:
MetaComp->SetFloatParameter(FName("Pitch"), 1.5f);
MetaComp->SetBoolParameter(FName("IsUnderwater"), true);
MetaComp->SetIntParameter(FName("SurfaceType"), 2);
MetaComp->SetTriggerParameter(FName("OnImpact")); // impulse trigger input
MetaComp->ResetParameters();| Criterion | SoundCue | MetaSound |
|---|---|---|
| Runtime parameters | Limited (wave params) | Typed inputs, full parameter system |
| Procedural audio | No | Yes (oscillators, noise, DSP filters) |
| Reactive to gameplay | Via parameter nodes | Native — bind any float/bool/trigger |
| Use when | Randomized pre-authored sounds | Adaptive music, procedural SFX, state-driven audio |
UMetaSoundSourceUSoundBaseUSoundBasecpp
// UAudioComponent实现了ISoundParameterControllerInterface:
MetaComp->SetFloatParameter(FName("Pitch"), 1.5f);
MetaComp->SetBoolParameter(FName("IsUnderwater"), true);
MetaComp->SetIntParameter(FName("SurfaceType"), 2);
MetaComp->SetTriggerParameter(FName("OnImpact")); // 脉冲触发输入
MetaComp->ResetParameters();| 评判标准 | SoundCue | MetaSound |
|---|---|---|
| 运行时参数 | 有限(波形参数) | 类型化输入,完整参数系统 |
| 程序化音频 | 不支持 | 支持(振荡器、噪声、DSP滤波器) |
| 游戏玩法响应 | 通过参数节点 | 原生支持——绑定任意float/bool/trigger |
| 使用场景 | 随机化的预制作声音 | 自适应音乐、程序化SFX、状态驱动音频 |
Submix Spectrum Analysis and Envelope Following (SoundSubmix.h)
子混音频谱分析与包络跟随(SoundSubmix.h)
cpp
// Envelope following:
SFXSubmix->StartEnvelopeFollowing(this);
FOnSubmixEnvelopeBP Env;
Env.BindDynamic(this, &AMyActor::OnSubmixEnvelope);
SFXSubmix->AddEnvelopeFollowerDelegate(this, Env);
SFXSubmix->StopEnvelopeFollowing(this);
// Callback: void OnSubmixEnvelope(const TArray<float>& Envelope);
// Spectrum analysis:
SFXSubmix->StartSpectralAnalysis(this,
EFFTSize::Medium, EFFTPeakInterpolationMethod::Linear,
EFFTWindowType::Hann, 0.0f, EAudioSpectrumType::MagnitudeSpectrum
);
TArray<FSoundSubmixSpectralAnalysisBandSettings> Bands;
FSoundSubmixSpectralAnalysisBandSettings LowBand;
LowBand.BandFrequency = 80.f; LowBand.AttackTimeMsec = 10.f; LowBand.ReleaseTimeMsec = 100.f;
Bands.Add(LowBand);
FOnSubmixSpectralAnalysisBP Spectral;
Spectral.BindDynamic(this, &AMyActor::OnSpectralAnalysis);
SFXSubmix->AddSpectralAnalysisDelegate(
this, Bands, Spectral,
30.f /*UpdateRateHz*/, -40.f /*DecibelFloor*/, true /*Normalize*/, false /*AutoRange*/
);
SFXSubmix->StopSpectralAnalysis(this);
// Callback: void OnSpectralAnalysis(const TArray<float>& Magnitudes);cpp
// 包络跟随:
SFXSubmix->StartEnvelopeFollowing(this);
FOnSubmixEnvelopeBP Env;
Env.BindDynamic(this, &AMyActor::OnSubmixEnvelope);
SFXSubmix->AddEnvelopeFollowerDelegate(this, Env);
SFXSubmix->StopEnvelopeFollowing(this);
// 回调函数:void OnSubmixEnvelope(const TArray<float>& Envelope);
// 频谱分析:
SFXSubmix->StartSpectralAnalysis(this,
EFFTSize::Medium, EFFTPeakInterpolationMethod::Linear,
EFFTWindowType::Hann, 0.0f, EAudioSpectrumType::MagnitudeSpectrum
);
TArray<FSoundSubmixSpectralAnalysisBandSettings> Bands;
FSoundSubmixSpectralAnalysisBandSettings LowBand;
LowBand.BandFrequency = 80.f; LowBand.AttackTimeMsec = 10.f; LowBand.ReleaseTimeMsec = 100.f;
Bands.Add(LowBand);
FOnSubmixSpectralAnalysisBP Spectral;
Spectral.BindDynamic(this, &AMyActor::OnSpectralAnalysis);
SFXSubmix->AddSpectralAnalysisDelegate(
this, Bands, Spectral,
30.f /*更新频率Hz*/, -40.f /*分贝下限*/, true /*归一化*/, false /*自动范围*/
);
SFXSubmix->StopSpectralAnalysis(this);
// 回调函数:void OnSpectralAnalysis(const TArray<float>& Magnitudes);Module Dependencies
模块依赖
csharp
// In .Build.cs:
PublicDependencyModuleNames.AddRange(new string[] { "Engine", "AudioMixer" });
PublicDependencyModuleNames.Add("MetasoundEngine"); // for MetaSound parameters
PublicDependencyModuleNames.Add("MetasoundFrontend");cpp
#include "Components/AudioComponent.h"
#include "Kismet/GameplayStatics.h"
#include "Sound/SoundBase.h"
#include "Sound/SoundCue.h"
#include "Sound/SoundWave.h"
#include "Sound/SoundAttenuation.h"
#include "Sound/SoundConcurrency.h"
#include "Sound/SoundSubmix.h"csharp
// 在.Build.cs中:
PublicDependencyModuleNames.AddRange(new string[] { "Engine", "AudioMixer" });
PublicDependencyModuleNames.Add("MetasoundEngine"); // 用于MetaSound参数
PublicDependencyModuleNames.Add("MetasoundFrontend");cpp
#include "Components/AudioComponent.h"
#include "Kismet/GameplayStatics.h"
#include "Sound/SoundBase.h"
#include "Sound/SoundCue.h"
#include "Sound/SoundWave.h"
#include "Sound/SoundAttenuation.h"
#include "Sound/SoundConcurrency.h"
#include "Sound/SoundSubmix.h"Audio Analysis
音频分析
Submix Spectrum and Envelope
子混音频谱与包络
See the existing submix analysis section above for real-time analysis via .
USoundSubmix有关通过进行实时分析的内容,请参阅上面的子混音分析部分。
USoundSubmixNon-Real-Time Analysis (NRT)
非实时分析(NRT)
UAudioAnalyzerNRTULoudnessNRTUOnsetNRTUAudioSynesthesiaNRTUAudioAnalyzerNRTFor offline audio analysis (e.g., beat detection for rhythmic gameplay), use the Audio Synesthesia plugin:
cpp
// Build.cs: "AudioSynesthesia"
#include "AudioSynesthesiaModule.h"
// Create an analyzer — LoudnessNRT analyzes an entire sound asset offline
ULoudnessNRT* Analyzer = NewObject<ULoudnessNRT>();
ULoudnessNRTSettings* Settings = NewObject<ULoudnessNRTSettings>();
Settings->AnalysisPeriod = 0.01f; // 10ms windows
Analyzer->Settings = Settings;
Analyzer->Sound = MySoundWave;
Analyzer->AnalyzeAudio(); // WITH_EDITOR only; call from editor utility or cook-time code
// Query results at specific timestamps
float Loudness;
Analyzer->GetLoudnessAtTime(1.5f, Loudness);
// For beat detection, use OnsetNRT:
UOnsetNRT* OnsetAnalyzer = NewObject<UOnsetNRT>();
OnsetAnalyzer->Sound = MySoundWave;
OnsetAnalyzer->AnalyzeAudio(); // WITH_EDITOR only
TArray<float> OnsetTimestamps;
TArray<float> OnsetStrengths;
OnsetAnalyzer->GetNormalizedChannelOnsetsBetweenTimes(
0.f, Duration, 0, OnsetTimestamps, OnsetStrengths);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.
UAudioAnalyzerNRTULoudnessNRTUOnsetNRTUAudioSynesthesiaNRTUAudioSynesthesiaNRTUAudioAnalyzerNRT对于离线音频分析(例如为节奏型游戏进行节拍检测),使用Audio Synesthesia插件:
cpp
// Build.cs中添加:"AudioSynesthesia"
#include "AudioSynesthesiaModule.h"
// 创建分析器 — LoudnessNRT离线分析整个声音资源
ULoudnessNRT* Analyzer = NewObject<ULoudnessNRT>();
ULoudnessNRTSettings* Settings = NewObject<ULoudnessNRTSettings>();
Settings->AnalysisPeriod = 0.01f; // 10ms窗口
Analyzer->Settings = Settings;
Analyzer->Sound = MySoundWave;
Analyzer->AnalyzeAudio(); // 仅在WITH_EDITOR模式下可用;从编辑器工具或烹饪时代码调用
// 查询特定时间点的结果
float Loudness;
Analyzer->GetLoudnessAtTime(1.5f, Loudness);
// 如需节拍检测,使用OnsetNRT:
UOnsetNRT* OnsetAnalyzer = NewObject<UOnsetNRT>();
OnsetAnalyzer->Sound = MySoundWave;
OnsetAnalyzer->AnalyzeAudio(); // 仅在WITH_EDITOR模式下可用
TArray<float> OnsetTimestamps;
TArray<float> OnsetStrengths;
OnsetAnalyzer->GetNormalizedChannelOnsetsBetweenTimes(
0.f, Duration, 0, OnsetTimestamps, OnsetStrengths);NRT的优势:预分析音轨以生成节拍图、音量曲线或 onset标记。在运行时使用这些数据实现音乐驱动的游戏玩法,无需每帧进行FFT计算的开销。
Common Mistakes and Anti-Patterns
常见错误与反模式
Spawning a new AudioComponent every fire event
cpp
// WRONG — leaks a component instance per call
UAudioComponent* Comp = NewObject<UAudioComponent>(this);
Comp->SetSound(FireSound); Comp->Play();
// CORRECT — fire-and-forget for one-shots
UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation());
// CORRECT — cache a single component for repeated/looping sounds
if (!CachedFireAudio) { CachedFireAudio = UGameplayStatics::SpawnSoundAttached(..., /*bAutoDestroy=*/false); }
CachedFireAudio->Play();Playing 3D sounds without attenuation
cpp
// WRONG — full volume at any distance
UGameplayStatics::PlaySoundAtLocation(this, FootstepSound, Location);
// CORRECT — pass or assign USoundAttenuation with sphere falloff tuned to gameplay scaleIgnoring concurrency on high-frequency sounds
cpp
// WRONG — 20 simultaneous explosions with default concurrency
UGameplayStatics::PlaySoundAtLocation(this, ExplosionSound, Location);
// CORRECT — pass USoundConcurrency: MaxCount=4, ResolutionRule=StopFarthestThenOldestPlaying audio on a dedicated server
cpp
// WRONG — FAudioDevice not initialized on server, causes crash/log spam
void AWeapon::Fire() { UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation()); }
// CORRECT
void AWeapon::Fire() {
if (GetNetMode() != NM_DedicatedServer) {
UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation());
}
}Forgetting to unbind delegates before destruction
cpp
// In EndPlay:
if (AudioComponent) { AudioComponent->OnAudioFinished.RemoveAll(this); AudioComponent->Stop(); }Using PlaySound2D for in-world sounds
cpp
// WRONG — no attenuation or spatialization
UGameplayStatics::PlaySound2D(this, GunShot);
// CORRECT
UGameplayStatics::PlaySoundAtLocation(this, GunShot, GetActorLocation());每次触发事件时生成新的AudioComponent
cpp
// 错误 — 每次调用都会泄漏组件实例
UAudioComponent* Comp = NewObject<UAudioComponent>(this);
Comp->SetSound(FireSound); Comp->Play();
// 正确 — 一次性播放的SFX使用该方式
UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation());
// 正确 — 缓存单个组件用于重复/循环播放的声音
if (!CachedFireAudio) { CachedFireAudio = UGameplayStatics::SpawnSoundAttached(..., /*bAutoDestroy=*/false); }
CachedFireAudio->Play();播放无衰减的3D声音
cpp
// 错误 — 任何距离下都是全音量
UGameplayStatics::PlaySoundAtLocation(this, FootstepSound, Location);
// 正确 — 传递或分配带有球体衰减的USoundAttenuation,并根据游戏玩法规模调整参数忽略高频声音的并发控制
cpp
// 错误 — 使用默认并发设置时会同时播放20个爆炸音
UGameplayStatics::PlaySoundAtLocation(this, ExplosionSound, Location);
// 正确 — 传递USoundConcurrency:MaxCount=4,ResolutionRule=StopFarthestThenOldest在专用服务器上播放音频
cpp
// 错误 — 服务器上未初始化FAudioDevice,会导致崩溃或日志垃圾信息
void AWeapon::Fire() { UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation()); }
// 正确
void AWeapon::Fire() {
if (GetNetMode() != NM_DedicatedServer) {
UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation());
}
}销毁前忘记解绑委托
cpp
// 在EndPlay中:
if (AudioComponent) { AudioComponent->OnAudioFinished.RemoveAll(this); AudioComponent->Stop(); }使用PlaySound2D播放世界中的声音
cpp
// 错误 — 无衰减或空间化
UGameplayStatics::PlaySound2D(this, GunShot);
// 正确
UGameplayStatics::PlaySoundAtLocation(this, GunShot, GetActorLocation());Platform and Edge Case Considerations
平台与边缘情况考量
- Mobile — 16–32 voice limit. Use aggressive concurrency. Prefer resident loading for SFX. Disable HRTF unless the platform supports it.
- Dedicated servers — Guard all audio calls with .
GetNetMode() != NM_DedicatedServer - Streaming audio — Set on long music SoundWave assets. Never load minutes of music resident.
LoadingBehavior = LoadOnDemand - App focus loss — Set on music/SFX submixes. For custom handling:
bMuteWhenBackgrounded = true
- 移动平台 — 16–32声道限制。使用严格的并发控制。SFX优先使用常驻加载。除非平台支持,否则禁用HRTF。
- 专用服务器 — 所有音频调用都需用进行判断。
GetNetMode() != NM_DedicatedServer - 音频流 — 长音乐SoundWave资源设置。绝不要将数分钟的音乐常驻加载。
LoadingBehavior = LoadOnDemand - 应用失去焦点 — 在音乐/SFX子混音上设置。如需自定义处理:
bMuteWhenBackgrounded = true
Focus Loss Handling
失去焦点处理
cpp
// In your GameInstance or AudioManager
FCoreDelegates::ApplicationWillDeactivateDelegate.AddUObject(
this, &UMyAudioManager::OnAppDeactivate);
void UMyAudioManager::OnAppDeactivate()
{
FAudioDeviceHandle Device = GEngine->GetMainAudioDevice();
if (Device.IsValid()) { Device->SetTransientPrimaryVolume(0.f); }
}- VR — Enable and
bSpatialize = trueon all 3D attenuation assets.SpatializationAlgorithm = SPATIALIZATION_HRTF - Audio LOD — Use to reduce priority of distant sounds before voice-budget culling.
bEnablePriorityAttenuation
cpp
// 在你的GameInstance或AudioManager中
FCoreDelegates::ApplicationWillDeactivateDelegate.AddUObject(
this, &UMyAudioManager::OnAppDeactivate);
void UMyAudioManager::OnAppDeactivate()
{
FAudioDeviceHandle Device = GEngine->GetMainAudioDevice();
if (Device.IsValid()) { Device->SetTransientPrimaryVolume(0.f); }
}- VR平台 — 在所有3D衰减资源上启用和
bSpatialize = true。SpatializationAlgorithm = SPATIALIZATION_HRTF - 音频LOD — 使用在声道预算耗尽前降低远处声音的优先级。
bEnablePriorityAttenuation
Related Skills
相关技能
- — UAudioComponent lifetime, attachment, and replication patterns
ue-actor-component-architecture - — synchronizing audio events with particle system callbacks
ue-niagara-effects - — delegate binding patterns, UPROPERTY and UFUNCTION macros
ue-cpp-foundations
- — UAudioComponent的生命周期、附加和复制模式
ue-actor-component-architecture - — 将音频事件与粒子系统回调同步
ue-niagara-effects - — 委托绑定模式、UPROPERTY和UFUNCTION宏
ue-cpp-foundations