关于 ue-audio-system
面向 UE 5.8 项目的音频系统开发技能,帮助开发者按任务查找经过版本核验的音频 API 与实现模式。内容涵盖资产、播放、路由、MetaSounds、同步和分析。
主要功能
- 01UE 5.8 音频 API 参考
- 02音频资产与播放控制
- 03衰减、空间化与并发
- 04混音、子混音与总线
- 05MetaSounds、调制与分析
适用场景
- 01为游戏角色触发音效
- 02配置音效分类和音量混音
- 03构建自适应音乐与合成音效
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ quodsoler/ unreal-engine-skills --skill ue-audio-system安装后在 Claude Code 中输入/ue-audio-system确认已加载。
附带文件references/audio-component-reference.mdreferences/audio-setup-patterns.md
详细介绍
UE Audio System
目标引擎:UE 5.8。下文中的 API 已依据 5.8 头文件验证;旧版形式列于“已弃用 — 请勿使用”部分。
涵盖声音资源、从 C++ 播放、衰减、并发、声音类和混音、子混音/总线布线、MetaSounds、调制、Quartz 和分析。引擎端代码位于 Engine/Classes/Sound 和 Components/AudioComponent.h(模块 Engine),混音器位于 AudioMixer,参数接口位于 AudioExtensions。插件模块:MetasoundEngine / MetasoundFrontend(MetaSounds)、AudioModulation、AudioSynesthesia(在 5.8 中为 Beta)、SubtitlesAndClosedCaptions(在 5.8 中为 Beta)。
// MyGame.Build.cs
PublicDependencyModuleNames.AddRange(new string[] { "Engine", "AudioMixer", "AudioExtensions" });
PrivateDependencyModuleNames.AddRange(new string[] { "MetasoundEngine", "MetasoundFrontend", "AudioModulation" });
上下文
如果 .agents/ue-project-context.md 存在,请阅读它(模块名称、约定、已启用的插件、GAS/网络配置)。如果该文件不存在,请继续操作。
根据请求和代码库确定所属领域。只有当两种合理理解会产生不同代码时,才提问。
| 请求涉及…… | 前往 |
|---|---|
| 应创建哪种资源(wave、cue、MetaSound)、流式传输 | 声音资源 |
| 从游戏逻辑代码触发声音 | 播放声音 |
| 淡入淡出、暂停、音量/音高、结束回调、单个实例发送 | UAudioComponent 控制 |
| 衰减、3D 声像、HRTF、遮挡、混响发送、焦点 | 衰减和空间化 |
| 声部过多、脚步声/枪声叠加、声部窃取 | 并发 |
| 按类别设置音量滑块、闪避、情境混音 | 声音类和声音混音 |
| 路由分组、主音量、音频总线、侧链源 | 子混音、总线和发送 |
| 为一组声音添加混响、均衡器、压缩 | 子混音效果 |
| 程序化/自适应音频、运行时参数、图表构建 | MetaSounds |
| 通过游戏逻辑曲线/LFO 连续控制参数 | 调制 |
| 与节拍同步的点缀音、速度、音乐量化 | Quartz 音乐同步 |
| 对音频作出响应(FFT、包络、离线节拍图) | 分析 |
| 字幕、对话文本 | 字幕 |
| 移动平台声部预算、专用服务器、后台运行、VR | 平台说明 |
| 完整的实用系统(音乐管理器、环境音、武器音效) | 音频设置模式 |
声音资源
USoundBase // abstract base (Sound/SoundBase.h)
├── USoundWave // imported PCM/compressed asset (Sound/SoundWave.h)
│ └── USoundSourceBus // sonifies a UAudioBus (Sound/SoundSourceBus.h)
├── USoundCue // node graph (Sound/SoundCue.h)
└── UMetaSoundSource // procedural graph, derives USoundWaveProcedural
每个资源都需要设置的 USoundBase 关键字段:SoundClassObject、AttenuationSettings、ConcurrencySet(或搭配 bOverrideConcurrency 的 ConcurrencyOverrides)、Priority(值越高,越不容易被声部裁剪)、SoundSubmixObject、SoundSubmixSends、BusSends / PreEffectBusSends / PostAttenuationBusSends、VirtualizationMode。
USoundCue 节点:USoundNodeRandom、USoundNodeModulator、USoundNodeMixer、USoundNodeAttenuation、USoundNodeLooping、USoundNodeDelay、USoundNodeDistanceCrossFade、USoundNodeConcatenator、USoundNodeSwitch、USoundNodeWavePlayer。USoundWave::LoadingBehavior(ESoundWaveLoadingBehavior、Sound/SoundWaveLoadingBehavior.h):Inherited、RetainOnLoad、PrimeOnLoad、LoadOnDemand、ForceInline。短音效使用 ForceInline,长音乐使用 LoadOnDemand,以免让数分钟的音频常驻内存。使用 GetLoadingBehavior(bCheckSoundClasses) 读取;在运行时使用 OverrideLoadingBehavior(ESoundWaveLoadingBehavior::LoadOnDemand) 覆盖。
| 标准 | USoundCue | UMetaSoundSource |
|---|---|---|
| 运行时参数 | 仅支持 Wave 参数 | 类型化输入(float、bool、int32、string、object、trigger) |
| 程序化 DSP | 否 | 是(振荡器、噪声、滤波器) |
| 在运行时从 C++ 构建 | 否 | 是 — UMetaSoundBuilderSubsystem |
| 适用于 | 随机化的预先创作单次音效 | 自适应音乐、由状态驱动和合成的音效 |
播放声音
所有函数都是 Kismet/GameplayStatics.h 中的 UGameplayStatics 静态函数。切勿在专用服务器上调用它们。
#include "Kismet/GameplayStatics.h" // + Components/SkeletalMeshComponent.h for GetMesh() below
// PlaySound2D(WorldContext, Sound, Volume=1, Pitch=1, StartTime=0,
// Concurrency=nullptr, OwningActor=nullptr, bIsUISound=true) — UI, music; no handle
UGameplayStatics::PlaySound2D(this, MenuSelectSound, 1.0f, 1.0f, 0.0f, nullptr, nullptr, true);
// PlaySoundAtLocation(WorldContext, Sound, Location, Rotation, Volume=1, Pitch=1, StartTime=0,
// Attenuation=nullptr, Concurrency=nullptr, OwningActor=nullptr, InitialParams=nullptr)
UGameplayStatics::PlaySoundAtLocation(this, GunShotSound, GetActorLocation(), FRotator::ZeroRotator,
1.0f, 1.0f, 0.0f, WeaponAttenuation, FireConcurrency, this);
// SpawnSoundAtLocation(WorldContext, Sound, Location, Rotation=ZeroRotator, Volume=1, Pitch=1,
// StartTime=0, Attenuation=nullptr, Concurrency=nullptr, bAutoDestroy=true)
UAudioComponent* Boom = UGameplayStatics::SpawnSoundAtLocation(this, ExplosionSound, Location,
FRotator::ZeroRotator, 1.0f, 1.0f, 0.0f, ExplosionAttenuation, nullptr, true);
// SpawnSoundAttached(Sound, AttachToComponent, AttachPointName=NAME_None, Location=FVector(ForceInit),
// Rotation=ZeroRotator, LocationType=EAttachLocation::KeepRelativeOffset,
// bStopWhenAttachedToDestroyed=false, Volume=1, Pitch=1, StartTime=0,
// Attenuation=nullptr, Concurrency=nullptr, bAutoDestroy=true)
UAudioComponent* EngineAudio = UGameplayStatics::SpawnSoundAttached(EngineLoopSound, GetMesh(),
TEXT("AudioSocket"), FVector::ZeroVector, FRotator::ZeroRotator,
EAttachLocation::SnapToTarget, /*bStopWhenAttachedToDestroyed=*/true,
1.0f, 1.0f, 0.0f, EngineAttenuation, nullptr, /*bAutoDestroy=*/false);
OwningActor 是按所有者限制并发(bLimitToOwner)时所依据的对象——声音属于某个 Actor 时,请传入该对象。SpawnSound2D 的前置参数与 PlaySound2D 相同,但以 bPersistAcrossLevelTransition, bAutoDestroy 结尾(没有 OwningActor/bIsUISound),并返回一个组件;CreateSound2D 接受与 SpawnSound2D 相同的参数,但返回的组件不会播放——请自行调用 Play()。
选择方式:单次播放使用即播即弃;需要淡出、停止或重新设置参数时,使用生成的句柄;永久的每个 Actor 循环音效,则使用 CreateDefaultSubobject<UAudioComponent> 成员。
UAudioComponent 控制
UAudioComponent(Components/AudioComponent.h)继承自 USceneComponent,并实现 ISoundParameterControllerInterface。
// Constructor
AudioComponent = CreateDefaultSubobject<UAudioComponent>(TEXT("AudioComponent"));
AudioComponent->SetupAttachment(RootComponent);
AudioComponent->bAutoActivate = false;
AudioComponent->bStopWhenOwnerDestroyed = true;
AudioComponent->bIsUISound = false; // true = keeps playing while the game is paused
// Playback — EAudioFaderCurve: Linear, Logarithmic, SCurve, Sin
AudioComponent->SetSound(EngineLoopSound);
AudioComponent->Play(/*StartTime=*/0.0f);
AudioComponent->FadeIn(0.5f, /*FadeVolumeLevel=*/1.0f, /*StartTime=*/0.0f, EAudioFaderCurve::Linear);
AudioComponent->AdjustVolume(/*Duration=*/0.25f, /*Level=*/0.3f, EAudioFaderCurve::Linear);
AudioComponent->FadeOut(1.0f, /*FadeVolumeLevel=*/0.0f, EAudioFaderCurve::Linear);
AudioComponent->SetVolumeMultiplier(0.5f);
AudioComponent->SetPitchMultiplier(1.2f);
AudioComponent->SetPaused(true);
AudioComponent->Stop();
const bool bPlaying = AudioComponent->IsPlaying();
// EAudioComponentPlayState: Playing, Stopped, Paused, FadingIn, FadingOut
const EAudioComponentPlayState State = AudioComponent->GetPlayState();
无需修改资源即可进行实例级路由和滤波:SetSubmixSend(USoundSubmixBase*, float)、SetSourceBusSendPreEffect / PostEffect / PostAttenuation、SetAudioBusSendPostEffect、SetLowPassFilterEnabled / SetLowPassFilterFrequency、对应的高通滤波器函数对,以及 SetOutputToBusOnly。若要内联设置衰减,请设置 bOverrideAttenuation = true,并填写 AttenuationOverrides(一个 FSoundAttenuationSettings)。
每个委托都有两种形式(Components/AudioComponent.h:441-481)。动态的 Blueprint 可见形式使用 AddDynamic 绑定 UFUNCTION。对应的 ...Native 形式使用 AddUObject 绑定,并会额外传入 UAudioComponent*。这些函数对包括 OnAudioFinished、OnAudioPlayStateChanged、OnAudioVirtualizationChanged、OnAudioPlaybackPercent、OnAudioSingleEnvelopeValue 和 OnAudioMultiEnvelopeValue。在 EndPlay 中使用 RemoveAll(this) 解除绑定。两种委托列表的代码见 references/audio-component-reference.md。
衰减与空间化
USoundAttenuation 资源封装了 FSoundAttenuationSettings(Sound/SoundAttenuation.h),后者继承自 FBaseAttenuationSettings(Engine/Attenuation.h)。
形状(EAttenuationShape::Type):Sphere、Capsule、Box、Cone。曲线(EAttenuationDistanceModel):Linear、Logarithmic、Inverse、LogReverse、NaturalSound、Custom。对于游戏中的声源,NaturalSound 最符合人耳感知的响度。
FSoundAttenuationSettings Settings;
Settings.DistanceAlgorithm = EAttenuationDistanceModel::NaturalSound; // FBaseAttenuationSettings
Settings.AttenuationShape = EAttenuationShape::Sphere;
Settings.FalloffDistance = 3000.0f;
Settings.bAttenuate = true;
Settings.bSpatialize = true;
// ESoundSpatializationAlgorithm: SPATIALIZATION_Default (panning), SPATIALIZATION_HRTF (plugin)
Settings.SpatializationAlgorithm = SPATIALIZATION_Default;
// Air absorption
Settings.bAttenuateWithLPF = true;
Settings.LPFRadiusMin = 1000.0f;
Settings.LPFRadiusMax = 6000.0f;
Settings.LPFFrequencyAtMin = 20000.0f;
Settings.LPFFrequencyAtMax = 800.0f;
// Occlusion
Settings.bEnableOcclusion = true;
Settings.OcclusionTraceChannel = ECC_Visibility;
Settings.OcclusionLowPassFilterFrequency = 300.0f;
Settings.OcclusionVolumeAttenuation = 0.5f;
Settings.OcclusionInterpolationTime = 0.1f;
// Reverb send — EReverbSendMethod: Linear | CustomCurve | Manual
Settings.bEnableReverbSend = true;
Settings.ReverbSendMethod = EReverbSendMethod::Linear;
Settings.ReverbWetLevelMin = 0.3f;
Settings.ReverbWetLevelMax = 0.95f;
Settings.ReverbDistanceMin = 400.0f;
Settings.ReverbDistanceMax = 4000.0f;
// Distant sounds lose the voice-budget fight first
Settings.bEnablePriorityAttenuation = true;
Settings.PriorityAttenuationMin = 1.0f;
Settings.PriorityAttenuationMax = 0.0f;
听众焦点(bEnableListenerFocus、FocusAzimuth、NonFocusAzimuth、FocusDistanceScale、NonFocusDistanceScale、NonFocusVolumeAttenuation)可让玩家注视的声音更加突出。bEnableSendToAudioLink 控制外部 AudioLink 路由——背景环境音请保持关闭。
并发
USoundConcurrency(Sound/SoundConcurrency.h)封装了 FSoundConcurrencySettings。通过 USoundBase::ConcurrencySet 进行赋值,或设置 bOverrideConcurrency 并填写 ConcurrencyOverrides。
FSoundConcurrencySettings& Rules = FireConcurrency->Concurrency; // struct ctor is not ENGINE_API — edit an asset's copy
Rules.MaxCount = 4;
Rules.bLimitToOwner = false;
// EMaxConcurrentResolutionRule::Type — PreventNew, StopOldest, StopFarthestThenPreventNew,
// StopFarthestThenOldest, StopLowestPriority, StopQuietest, StopLowestPriorityThenPreventNew
Rules.ResolutionRule = EMaxConcurrentResolutionRule::StopFarthestThenOldest;
Rules.RetriggerTime = 0.05f; // minimum seconds between plays in this group
Rules.VoiceStealReleaseTime = 0.08f; // fade for evicted voices; 0 clicks
Rules.VolumeScaleMode = EConcurrencyVolumeScaleMode::Distance; // Default | Distance | Priority
Rules.bVolumeScaleCanRelease = true;
Rules.VolumeScaleAttackTime = 0.01f;
Rules.VolumeScaleReleaseTime = 0.5f;
每类声音(脚步声、撞击声、子弹呼啸声)共用一个并发资源。达到 MaxCount 时,由 USoundBase::Priority 决定哪些声音继续播放。
声音类与声音混合
USoundClass 为每个声音提供一个类别,可在 FSoundClassProperties 中为其设置独立的 Volume/Pitch,并建立父子层级。USoundMix 包含 TArray<FSoundClassAdjuster> SoundClassEffects(SoundClassObject、VolumeAdjuster、PitchAdjuster、bApplyToChildren)以及 FadeInTime。
UGameplayStatics::SetBaseSoundMix(this, DefaultMix); // usually once, or via AudioSettings
UGameplayStatics::PushSoundMixModifier(this, CombatMix); // layers on top
UGameplayStatics::PopSoundMixModifier(this, CombatMix);
UGameplayStatics::ClearSoundMixModifiers(this);
// Duck one class inside an already-pushed mix
UGameplayStatics::SetSoundMixClassOverride(this, CombatMix, MusicClass,
/*Volume=*/0.3f, /*Pitch=*/1.0f, /*FadeInTime=*/0.5f, /*bApplyToChildren=*/true);
UGameplayStatics::ClearSoundMixClassOverride(this, CombatMix, MusicClass, /*FadeOutTime=*/1.0f);
声音类适用于由游戏逻辑驱动的闪避混音。玩家音量滑块应使用子混音输出音量——它是单一的线性增益,无需清理堆栈。
子混音、总线与发送
USoundSubmixBase (Sound/SoundSubmix.h)
├── USoundSubmixWithParentBase
│ ├── USoundSubmix // effect chain, analysis, recording
│ └── USoundfieldSubmix // ambisonics / soundfield
├── UEndpointSubmix
└── USoundfieldEndpointSubmix
MusicSubmix->SetSubmixOutputVolume(this, 0.5f); // linear gain
MusicSubmix->SetSubmixWetLevel(this, 1.0f);
MusicSubmix->SetSubmixDryLevel(this, 0.0f);
MusicSubmix->DynamicConnect(this, MasterSubmix); // re-parent at runtime
MusicSubmix->DynamicDisconnect(this);
在音乐/音效子混音上将 bMuteWhenBackgrounded = true,使应用失去焦点时它们停止播放。
发送。 FSoundSubmixSendInfo(Sound/SoundSubmixSend.h)和 FSoundSourceBusSendInfo(Sound/SoundSourceBusSend.h)的结构相同:控制方法(ESendLevelControlMethod/ESourceBusSendLevelControlMethod——Linear、CustomCurve、Manual)、SendLevel 或 MinSendLevel/MaxSendLevel + MinSendDistance/MaxSendDistance、CustomSendLevelCurve,以及在 5.8 中显式指定的一对滤波器:
FSoundSubmixSendInfo Send;
Send.SoundSubmix = ReverbSubmix;
Send.SendLevelControlMethod = ESendLevelControlMethod::Manual;
Send.SendLevel = 0.35f;
Send.SendStage = ESubmixSendStage::PostDistanceAttenuation; // or PreDistanceAttenuation
Send.bEnableLPFCutoff = true;
Send.LPFCutoff = 3000.0f; // Hz, 20..20000
Send.bEnableHPFCutoff = false;
Send.HPFCutoff = 20.0f;
音频总线。 UAudioBus(Sound/AudioBus.h,EAudioBusChannels 类型的 AudioBusChannels)是运行时接入点:声音发送到其中,USoundSourceBus 将其转回声音,子混音也可以注册它。总线可用于将信号馈送到侧链压缩器或分析器,而无需额外的播放路径。
UAudioMixerBlueprintLibrary::StartAudioBus(this, DuckingBus);
UAudioMixerBlueprintLibrary::RegisterAudioBusToSubmix(this, AnalysisSubmix, DuckingBus);
const bool bActive = UAudioMixerBlueprintLibrary::IsAudioBusActive(this, DuckingBus);
UAudioMixerBlueprintLibrary::UnregisterAudioBusFromSubmix(this, AnalysisSubmix, DuckingBus);
UAudioMixerBlueprintLibrary::StopAudioBus(this, DuckingBus);
子混音效果
USoundSubmix::SubmixEffectChain 是一个 TArray<TObjectPtr<USoundEffectSubmixPreset>>。AudioMixer/Classes/SubmixEffects 中提供的预设包括:USubmixEffectReverbPreset、USubmixEffectSubmixEQPreset、USubmixEffectDynamicsProcessorPreset。
#include "AudioMixerBlueprintLibrary.h"
#include "SubmixEffects/AudioMixerSubmixEffectReverb.h"
USubmixEffectReverbPreset* Preset = NewObject<USubmixEffectReverbPreset>(this);
FSubmixEffectReverbSettings ReverbSettings;
ReverbSettings.DecayTime = 2.5f;
ReverbSettings.Density = 0.85f;
ReverbSettings.Diffusion = 0.8f;
ReverbSettings.WetLevel = 0.4f;
Preset->SetSettings(ReverbSettings); // thread-safe; assigning Settings directly is editor-time only
const int32 ChainIndex = UAudioMixerBlueprintLibrary::AddSubmixEffect(this, ReverbSubmix, Preset);
UAudioMixerBlueprintLibrary::RemoveSubmixEffect(this, ReverbSubmix, Preset);
UAudioMixerBlueprintLibrary::RemoveSubmixEffectAtIndex(this, ReverbSubmix, ChainIndex);
UAudioMixerBlueprintLibrary::ClearSubmixEffects(this, ReverbSubmix);
使用 SetSubmixEffectChainOverride(WorldContext, Submix, Chain, FadeTimeSec) 和 ClearSubmixEffectChainOverride(WorldContext, Submix, FadeTimeSec) 可为某个环境替换整条效果链。AddMasterSubmixEffect/RemoveMasterSubmixEffect/ClearMasterSubmixEffects 则作用于主子混音。
源端效果使用 USoundEffectSourcePresetChain(Sound/SoundEffectSource.h)中的 USoundEffectSourcePreset。AAudioVolume 会根据音量区域应用 FReverbSettings、FInteriorSettings 和子混音发送/覆盖设置,并按 Priority 排序。
MetaSounds
UMetaSoundSource 派生自 USoundWaveProcedural → USoundWave → USoundBase,因此可通过上述所有函数播放。通过 ISoundParameterControllerInterface 驱动其类型化输入;UAudioComponent 实现了该接口(其基础接口 IAudioParameterControllerInterface 位于 AudioExtensions/Public/AudioParameterControllerInterface.h)。
EngineAudioComp->SetFloatParameter(FName("RPM"), CurrentRPM);
EngineAudioComp->SetBoolParameter(FName("Engaged"), bEngaged);
EngineAudioComp->SetIntParameter(FName("GearIndex"), Gear);
EngineAudioComp->SetStringParameter(FName("SurfaceName"), TEXT("Gravel"));
EngineAudioComp->SetObjectParameter(FName("ImpactWave"), ImpactWave);
EngineAudioComp->SetTriggerParameter(FName("OnGearShift"));
EngineAudioComp->ResetParameters();
// Batch — cheaper than one call per value; SetParameters takes an rvalue array
TArray<FAudioParameter> Batch;
Batch.Emplace(FAudioParameter(FName("RPM"), CurrentRPM));
Batch.Emplace(FAudioParameter(FName("Engaged"), bEngaged));
EngineAudioComp->SetParameters(MoveTemp(Batch));
参数名称必须与 MetaSound 图表输入完全一致。在声音不是 MetaSound 的组件上设置参数会被忽略,不会报错。
UMetasoundGeneratorHandle::CreateMetaSoundGeneratorHandle(AudioComponent)(MetasoundGeneratorHandle.h)可访问正在运行的生成器:IsValid()、GetAudioComponentId()、ApplyParameterPack(UMetasoundParameterPack*)、GetGenerator(),以及 OnGeneratorHandleAttached/OnGeneratorHandleDetached。使用 UMetaSoundOutputSubsystem::WatchOutput 读取图表输出。
使用 UMetaSoundBuilderSubsystem::Get() → CreateSourceBuilder/CreatePatchBuilder/CreateSourcePresetBuilder 可通过代码构建图表,随后调用 AddGraphInputNode、AddNodeByClassName、ConnectNodes、SetNodeInputDefault 和 Audition。Build(const FMetaSoundBuilderOptions&) 仅在 WITH_EDITORONLY_DATA 下可用;运行时请使用 Audition 或 BuildNewMetaSound(FName)(MetasoundBuilderBase.h:586)。底层文档 API 为 FMetaSoundFrontendDocumentBuilder(MetasoundFrontend/Public/MetasoundFrontendDocumentBuilder.h)。示例:音频设置模式。
调制
AudioModulation 插件将连续控制信号路由到音量、音高和滤波器截止频率。USoundControlBus 携带一个值,USoundModulationGenerator 生成一个值(LFO、包络跟随器),USoundControlBusMix 设置总线目标,USoundModulationPatch 在参数之间建立映射。总线、生成器和 Patch 均派生自 USoundModulatorBase;USoundControlBusMix 是一个普通的 UObject(SoundControlBusMix.h:37)。
// EModulationDestination: Volume, Pitch, Lowpass, Highpass
// EModulationRouting: Disable, Inherit, Override, Union
TSet<USoundModulatorBase*> Modulators;
Modulators.Add(TensionControlBus);
AudioComponent->SetModulationRouting(Modulators, EModulationDestination::Volume, EModulationRouting::Override);
AudioComponent->AddModulationRouting(Modulators, EModulationDestination::Lowpass);
AudioComponent->RemoveModulationRouting(Modulators, EModulationDestination::Lowpass);
const TSet<USoundModulatorBase*> Current = AudioComponent->GetModulators(EModulationDestination::Volume);
在资源上,调制信息位于 FSoundModulationDestinationSettings(Sound/SoundModulationDestination.h)中:包含一个基础 Value,以及一个 TSet<TObjectPtr<USoundModulatorBase>> Modulators。在原生 Audio::FModulationDestination 代码中,设置器名为 SetModulators。
Quartz 音乐同步
UQuartzSubsystem 是一个 UTickableWorldSubsystem(AudioMixer/Public/Quartz/QuartzSubsystem.h),用于运行采样精度的音乐时钟。
#include "Quartz/QuartzSubsystem.h"
#include "Quartz/AudioMixerClockHandle.h"
UQuartzSubsystem* Quartz = GetWorld()->GetSubsystem<UQuartzSubsystem>();
FQuartzClockSettings ClockSettings; // TimeSignature defaults to 4/4
// Handle-taking calls use UQuartzClockHandle*& — pass a raw local, not a TObjectPtr member
UQuartzClockHandle* ClockHandle = Quartz->CreateNewClock(this, TEXT("MusicClock"), ClockSettings,
/*bOverrideSettingsIfClockExists=*/false, /*bUseAudioEngineClockManager=*/true);
ClockHandle->StartClock(this, ClockHandle);
// EQuartzCommandQuantization: Bar, Beat, ThirtySecondNote and the other note values
FQuartzQuantizationBoundary Boundary;
Boundary.Quantization = EQuartzCommandQuantization::Bar;
Boundary.Multiplier = 1.0f;
Boundary.CountingReferencePoint = EQuarztQuantizationReference::BarRelative;
Boundary.bFireOnClockStart = true;
FOnQuartzCommandEventBP OnQueued;
StingerComponent->PlayQuantized(this, ClockHandle, Boundary, OnQueued,
/*InStartTime=*/0.0f, /*InFadeInDuration=*/0.0f, /*InFadeVolumeLevel=*/1.0f, EAudioFaderCurve::Linear);
使用 ClockHandle->SubscribeToQuantizationEvent(this, EQuartzCommandQuantization::Beat, OnBeat, ClockHandle)(或 SubscribeToAllQuantizationEvents)订阅节拍器;FOnQuartzMetronomeEventBP 回调接收 (FName ClockName, EQuartzCommandQuantization, int32 NumBars, int32 Beat, float BeatFraction)。节奏变更通过 SetBeatsPerMinute 进行,该操作本身也会量化。
分析
实时分析,使用 USoundSubmix:
MySFXSubmix->StartEnvelopeFollowing(this);
FOnSubmixEnvelopeBP EnvelopeDelegate;
EnvelopeDelegate.BindDynamic(this, &AMyActor::OnSubmixEnvelope);
MySFXSubmix->AddEnvelopeFollowerDelegate(this, EnvelopeDelegate);
MySFXSubmix->StartSpectralAnalysis(this, EFFTSize::Medium, EFFTPeakInterpolationMethod::Linear,
EFFTWindowType::Hann, /*HopSize=*/0.0f, EAudioSpectrumType::MagnitudeSpectrum);
MySFXSubmix->StopSpectralAnalysis(this);
MySFXSubmix->StopEnvelopeFollowing(this);
基于频段的 FFT 回调通过 AddSpectralAnalysisDelegate(WorldContext, BandSettings, Delegate, UpdateRate, DecibelNoiseFloor, bDoNormalize, bDoAutoRange, AutoRangeAttackTime, AutoRangeReleaseTime) 实现,参数中包含一个 FSoundSubmixSpectralAnalysisBandSettings 数组——参见音频设置模式。UAudioMixerBlueprintLibrary::MakeMusicalSpectralAnalysisBandSettings、MakeFullSpectrumSpectralAnalysisBandSettings 和 MakePresetSpectralAnalysisBandSettings 可为你构建这些数组;StartAnalyzingOutput / StopAnalyzingOutput 配合 GetMagnitudeForFrequencies / GetPhaseForFrequencies 可提供轮询 API。录制使用 StartRecordingOutput / StopRecordingOutput(EAudioRecordingExportType::SoundWave 或 WavFile)。
离线分析使用 AudioSynesthesia 插件(在 5.8 中为 Beta):ULoudnessNRT 和 UOnsetNRT 派生自 UAudioSynesthesiaNRT → UAudioAnalyzerNRT。AnalyzeAudio() 仅适用于 WITH_EDITOR——在 cook 时烘焙节拍图,然后在运行时使用 GetLoudnessAtTime / GetNormalizedChannelOnsetsBetweenTimes 读取。完整示例见音频设置模式。
字幕
SubtitlesAndClosedCaptions 插件(在 5.8 中为 Beta)通过 USubtitlesBlueprintFunctionLibrary 驱动字幕:
#include "SubtitlesBlueprintFunctionLibrary.h"
USubtitlesBlueprintFunctionLibrary::QueueSingleSubtitle(
FText::FromString(TEXT("Contact, north ridge.")), /*Duration=*/2.5f, /*StartOffset=*/0.0f,
/*Priority=*/1.0f, ESubtitleType::Subtitle, ESubtitleTiming::InternallyTimed);
USubtitlesBlueprintFunctionLibrary::StopAllSubtitles();
QueueSubtitlesFromAsset / StopSubtitlesInAsset 接收附加到声音上的 USubtitleAssetUserData。引擎端的 FSubtitleManager(Engine/Public/SubtitleManager.h)仍可用于 USoundWave::Subtitles 提示。
平台说明
- Windows 后端 — 在
Config/Windows/BaseWindowsEngine.ini中设置AudioMixerModuleName=AudioMixerWasapi。XAudio2(AudioMixerXAudio2)仍可按项目选择。 - 专用服务器 — 没有音频设备。每次播放调用都应使用
GetNetMode() != NM_DedicatedServer进行保护。 - 移动平台 — 语音预算紧张。充分利用并发和
Priority,避免使用SPATIALIZATION_HRTF,较短的音效优先使用ForceInline。 - 进入后台 — 使用子混音上的
bMuteWhenBackgrounded,或挂接FCoreDelegates::ApplicationWillDeactivateDelegate,并在GEngine->GetMainAudioDevice()上调用FAudioDevice::SetTransientPrimaryVolume(0.0f)。 - VR — 对 3D 衰减资源设置
bSpatialize = true和SPATIALIZATION_HRTF,并由空间化插件提供支持。 - 音高范围 — 由
UAudioSettings::GlobalMinPitchScale/GlobalMaxPitchScale限制。
已弃用 — 请勿使用
| 不要使用 | 在 5.8 中使用 | 来源 |
|---|---|---|
USubmixEffectEQPreset | USubmixEffectSubmixEQPreset | 从未存在;实际类位于 SubmixEffects/AudioMixerSubmixEffectEQ.h:110 |
FSoundSubmixSendInfo::LPFCutoffFrequency | bEnableLPFCutoff + LPFCutoff | Sound/SoundSubmixSend.h:157 中标记为 UE_DEPRECATED(5.8) |
FSoundSubmixSendInfo::HPFCutoffFrequency | bEnableHPFCutoff + HPFCutoff | Sound/SoundSubmixSend.h:161 中标记为 UE_DEPRECATED(5.8) |
FSoundSourceBusSendInfo::LPFCutoffFrequency | bEnableLPFCutoff + LPFCutoff | Sound/SoundSourceBusSend.h:86 中标记为 UE_DEPRECATED(5.8) |
Audio::FModulationDestination::UpdateModulators | SetModulators | Sound/SoundModulationDestination.h:198 中标记为 UE_DEPRECATED(5.8) |
Audio::FModulationDestination::UpdateModulator | SetModulators | Sound/SoundModulationDestination.h:195 中标记为 UE_DEPRECATED(5.1) |
USoundWave::CreateSoundWaveProxy | GetSoundWaveProxy() | Sound/SoundWave.h:1204 中标记为 UE_DEPRECATED(5.8) |
FSoundWaveProxy::GetZerothChunk 及其他代理访问器 | 保存 GetSoundWaveDataRef() 的结果 | Sound/SoundWave.h:1813 中标记为 UE_DEPRECATED(5.8) |
FSoundWaveProxyReader | FSoundWaveProxyPlayer | Sound/SoundWaveProxyReader.h:19 中标记为 UE_DEPRECATED(5.8) |
USubtitlesBlueprintFunctionLibrary::QueueSubtitle | QueueSingleSubtitle | SubtitlesBlueprintFunctionLibrary.h:32 中标记为 UE_DEPRECATED(5.8) |
UAudioBusSubsystem::StartAudioBus(Key, Channels, bAutomatic) | 接受 InAudioBusName 的重载 | AudioMixer/Public/AudioBusSubsystem.h:83 中标记为 UE_DEPRECATED(5.6) |
UAudioMixerBlueprintLibrary::RemoveSubmixEffectPreset | RemoveSubmixEffect | AudioMixerBlueprintLibrary.h:242 中标记为 UE_DEPRECATED(4.27) |
UAudioMixerBlueprintLibrary::ReplaceSoundEffectSubmix | ReplaceSubmixEffect | AudioMixerBlueprintLibrary.h:258 中标记为 UE_DEPRECATED(4.27) |
FAudioDevice::SetTransientMasterVolume | SetTransientPrimaryVolume | Engine/Public/AudioDevice.h:1892 中标记为 UE_DEPRECATED(5.1) |
FAudioComponentParam | FAudioParameter | Components/AudioComponent.h:133 中标记为 UE_DEPRECATED(5.0) |
USoundBase::SoundConcurrencySettings_DEPRECATED | ConcurrencySet / ConcurrencyOverrides | Sound/SoundBase.h:183 中的 _DEPRECATED 属性 |
常见错误
每次播放一次性音效都生成一个组件: 每次调用 NewObject<UAudioComponent> 都会留下一个未附加、未注册的组件。
// WRONG
UAudioComponent* Comp = NewObject<UAudioComponent>(this);
Comp->SetSound(FireSound);
Comp->Play();
// RIGHT — one-shot
UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation());
在专用服务器上播放音频: 专用服务器没有音频设备,因此该调用只会白白消耗资源并刷屏输出日志。
if (GetNetMode() != NM_DedicatedServer)
{
UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation());
}
将 PlaySound2D 用于世界空间音效: 2D 播放会完全跳过衰减和空间化,因此地图另一端的枪声也会以最大音量在正中央响起。请将 PlaySoundAtLocation 与 USoundAttenuation 配合使用。
将循环音效设为 bAutoDestroy = true: 音效首次报告播放完毕时句柄就会失效,后续调用 FadeOut 会访问已失效的组件。对于需要保留指针的对象,请传入 bAutoDestroy = false。
在 PlaySoundAtLocation 中忘记设置 OwningActor: 此时 bLimitToOwner 并发限制会退回到组级限制(FConcurrencyHandle::GetMode,SoundConcurrency.cpp:179),因此单个 Actor 的限制会悄然变成全局限制。
在 EndPlay 之后仍保留已绑定的委托: 请在 EndPlay 中调用 OnAudioFinished.RemoveAll(this) 和 Stop(),否则被池化或自动销毁的组件会在失效对象上触发回调。
通过 Sound Mix 调节音量滑块: Mix 的推入和弹出采用栈结构,若遗漏弹出操作,游戏音量就会一直降低。用户设置请使用 USoundSubmix::SetSubmixOutputVolume;Mix 应留给游戏过程中临时降低音量的场景。
在运行时直接赋值 Preset->Settings: 音频渲染线程读取的是它自己的副本。请改为在 Preset 上调用 SetSettings。
相关技能
ue-niagara-effects— 与音频事件同步的粒子系统和特效时序ue-animation-system— 触发脚步声、拟音和对白的动画通知ue-actor-component-architecture— 音频组件的生命周期、附加和复制ue-gameplay-framework— 音频管理器所在位置(GameInstance、子系统、玩家控制器)ue-data-assets-tables— 用于表面/冲击音效的、数据驱动的声音库和查找表ue-sequencer-cinematics— Level Sequence 中的音轨、对白和音乐ue-cpp-foundations— 委托绑定、UPROPERTY/UFUNCTION和子系统访问模式