mcpField
U
ue-audio-system

ue-audio-system

github.com/quodsoler开发4191.1k 次安装4 周前更新
代码仓库

关于 ue-audio-system

面向 UE 5.8 项目的音频系统开发技能,帮助开发者按任务查找经过版本核验的音频 API 与实现模式。内容涵盖资产、播放、路由、MetaSounds、同步和分析。

主要功能

  1. 01UE 5.8 音频 API 参考
  2. 02音频资产与播放控制
  3. 03衰减、空间化与并发
  4. 04混音、子混音与总线
  5. 05MetaSounds、调制与分析

适用场景

  1. 01为游戏角色触发音效
  2. 02配置音效分类和音量混音
  3. 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) 覆盖。

标准USoundCueUMetaSoundSource
运行时参数仅支持 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 中使用来源
USubmixEffectEQPresetUSubmixEffectSubmixEQPreset从未存在;实际类位于 SubmixEffects/AudioMixerSubmixEffectEQ.h:110
FSoundSubmixSendInfo::LPFCutoffFrequencybEnableLPFCutoff + LPFCutoffSound/SoundSubmixSend.h:157 中标记为 UE_DEPRECATED(5.8)
FSoundSubmixSendInfo::HPFCutoffFrequencybEnableHPFCutoff + HPFCutoffSound/SoundSubmixSend.h:161 中标记为 UE_DEPRECATED(5.8)
FSoundSourceBusSendInfo::LPFCutoffFrequencybEnableLPFCutoff + LPFCutoffSound/SoundSourceBusSend.h:86 中标记为 UE_DEPRECATED(5.8)
Audio::FModulationDestination::UpdateModulatorsSetModulatorsSound/SoundModulationDestination.h:198 中标记为 UE_DEPRECATED(5.8)
Audio::FModulationDestination::UpdateModulatorSetModulatorsSound/SoundModulationDestination.h:195 中标记为 UE_DEPRECATED(5.1)
USoundWave::CreateSoundWaveProxyGetSoundWaveProxy()Sound/SoundWave.h:1204 中标记为 UE_DEPRECATED(5.8)
FSoundWaveProxy::GetZerothChunk 及其他代理访问器保存 GetSoundWaveDataRef() 的结果Sound/SoundWave.h:1813 中标记为 UE_DEPRECATED(5.8)
FSoundWaveProxyReaderFSoundWaveProxyPlayerSound/SoundWaveProxyReader.h:19 中标记为 UE_DEPRECATED(5.8)
USubtitlesBlueprintFunctionLibrary::QueueSubtitleQueueSingleSubtitleSubtitlesBlueprintFunctionLibrary.h:32 中标记为 UE_DEPRECATED(5.8)
UAudioBusSubsystem::StartAudioBus(Key, Channels, bAutomatic)接受 InAudioBusName 的重载AudioMixer/Public/AudioBusSubsystem.h:83 中标记为 UE_DEPRECATED(5.6)
UAudioMixerBlueprintLibrary::RemoveSubmixEffectPresetRemoveSubmixEffectAudioMixerBlueprintLibrary.h:242 中标记为 UE_DEPRECATED(4.27)
UAudioMixerBlueprintLibrary::ReplaceSoundEffectSubmixReplaceSubmixEffectAudioMixerBlueprintLibrary.h:258 中标记为 UE_DEPRECATED(4.27)
FAudioDevice::SetTransientMasterVolumeSetTransientPrimaryVolumeEngine/Public/AudioDevice.h:1892 中标记为 UE_DEPRECATED(5.1)
FAudioComponentParamFAudioParameterComponents/AudioComponent.h:133 中标记为 UE_DEPRECATED(5.0)
USoundBase::SoundConcurrencySettings_DEPRECATEDConcurrencySet / ConcurrencyOverridesSound/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 和子系统访问模式

评论

支持 Markdown