关于 roblox-audio
roblox-audio 技能为 Roblox 开发者提供音频系统的参考和实现指南,重点介绍模块化音频图、旧版 Sound 系统及两者的选择、脚本和性能实践。
主要功能
- 01音频图对象与连接方式
- 022D 和 3D 音频配置
- 03音效与声学模拟
- 04AudioPlayer 播放控制
- 05客户端与服务器音频实践
- 06性能和资源权限说明
适用场景
- 01为新体验搭建音频图
- 02实现带距离衰减的 3D 音频
- 03制作文本转语音或语音转文本
- 04优化音频预加载与效果开销
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ nonlooped/ roblox-suite --skill roblox-audio安装后在 Claude Code 中输入/roblox-audio确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/audio-effects.mdaudio-graph-vs-sound.mdscripts/AudioBus.lua详细介绍
roblox-audio
官方来源:
- https://create.roblox.com/docs/en-us/audio/objects(音频图概览)
- https://create.roblox.com/docs/en-us/audio/effects(音频效果)
- https://create.roblox.com/docs/en-us/reference/engine/classes/Sound(旧版
Sound) - https://create.roblox.com/docs/en-us/reference/engine/classes/SoundService
- 引擎类:
AudioPlayer、AudioEmitter、AudioListener、AudioDeviceOutput、AudioDeviceInput、AudioTextToSpeech、AudioSpeechToText、Wire、AudioEqualizer、AudioCompressor、AudioReverb、AudioChorus、AudioDistortion、AudioEcho、AudioFlanger、AudioPitchShifter、AudioTremolo、AudioFader、AudioAnalyzer - 完整参考:https://create.roblox.com/docs/en-us/reference/engine
Roblox 建议优先使用音频对象,而不是 Sound、SoundGroup 和 SoundEffect。新开发内容应使用音频图;如果音频图没有优势,旧代码可以继续使用 Sound。
交叉参考:
- 服务和脚本位置请参阅 roblox-core/SKILL.md。
- 如何通过动画标记驱动音频(脚步声、撞击声),请参阅 roblox-animation/SKILL.md。
- UI 触发的声音反馈请参阅 roblox-user-interfaces/SKILL.md。
- 客户端权威的装饰性音频与服务器权威的游戏音频,请参阅 roblox-networking/SKILL.md。
两种系统
现代音频图(新开发内容推荐使用)
采用模块化实例,模拟现实世界的音频设备。每个对象都会生成、接收、修改或传输音频流。使用 Wire 实例将它们连接起来(SourceInstance → TargetInstance)。
| 对象 | 作用 | 现实世界中的对应物 |
|---|---|---|
AudioPlayer | 从音频资源 ID 生成音频流 | 音频文件播放器 |
AudioEmitter | 向 3D 环境中发射音频流(父级位置 = 发射点) | 世界中的扬声器 |
AudioListener | 接收环境中的音频流(父级 = 摄像机或角色) | 世界中的麦克风 |
AudioDeviceOutput | 将音频流播放到玩家的实体扬声器/耳机 | 玩家硬件输出设备 |
AudioDeviceInput | 从玩家的实体麦克风采集音频 | 玩家硬件麦克风 |
AudioTextToSpeech | 使用人造语音将文本转换为音频 | TTS 引擎 |
AudioSpeechToText | 将语音音频转换为文本 | 转录引擎 |
Wire | 将音频流从 SourceInstance 传输到 TargetInstance | 音频线缆 |
效果(全部属于“修改”类别):AudioEqualizer、AudioCompressor、AudioReverb、AudioChorus、AudioDistortion、AudioEcho、AudioFlanger、AudioPitchShifter、AudioTremolo、AudioFader、AudioAnalyzer。请参阅 references/audio-effects.md。
旧版 Sound 系统(仍可使用,但不推荐)
将 Sound 设为 BasePart 或 Attachment 的子级,即可从该位置发出声音,并使用内置的多普勒效应和距离衰减(RollOffMode、RollOffMaxDistance、RollOffMinDistance、EmitterSize)。“全局”Sound(未设为零件或附件的子级)会以恒定音量在各处播放。SoundGroup 控制组音量和效果;SoundEffect 子类(如 EqualizerSoundEffect、ReverbSoundEffect 等)会应用组级效果。SoundService 提供全局属性(AmbientReverb、DistanceFactor、DopplerScale、RespectFilteringEnabled),这些属性会影响 Sound 播放。
SoundService.AmbientReverb 和多普勒/距离属性仅影响旧版 Sound,不会影响音频图。音频图有自己的效果对象和每个发射器的 DistanceAttenuation 曲线。
决策树:该使用哪种系统?
- 全新体验、从零开始构建音频 → 音频图。它支持 TTS、STT、声学模拟和路由。
- 无需路由或效果的简单 2D 音效或音乐 →
Sound足够好,也更简单。不要只为了迁移而重写能正常工作的旧代码。 - 使用自定义衰减曲线的 3D 定位音频 → 音频图(
AudioEmitter.DistanceAttenuation)。 - 多个音源经过同一个效果(例如,所有枪声都经过同一个压缩器) → 音频图(一个效果,接入多个播放器)。
- 文本转语音或语音转文本 → 音频图(只有音频图支持
AudioTextToSpeech/AudioSpeechToText)。 - 语音聊天 / 空间语音 →
VoiceChatService(与体验内音频分开;启用UseAudioApi后,底层会使用AudioDeviceInput)。 - 声学模拟(遮挡、衍射、混响) → 音频图,启用
SoundService.AcousticSimulationEnabled = true,并在发射器 / 监听器上启用各自的AcousticSimulationEnabled。 - 快速原型 / 一次性 UI 点击音效 → 使用
Sound即可。
请参阅 references/audio-graph-vs-sound.md,了解并排的属性对照表和迁移说明。
2D 音频(非定向)
各处音量相同。需要:AudioPlayer → Wire → AudioDeviceOutput,并且都以 SoundService 为父级。
--!strict
local SoundService = game:GetService("SoundService")
local player = Instance.new("AudioPlayer")
player.AssetId = "rbxassetid://YOUR_AUDIO_ID"
player.Looping = true
player.Volume = 1
player.Parent = SoundService
local output = Instance.new("AudioDeviceOutput")
output.Parent = SoundService
local wire = Instance.new("Wire")
wire.SourceInstance = player
wire.TargetInstance = output
wire.Parent = SoundService
player:Play()
3D 音频(定位音频)
音量会随监听器与发射器之间的距离而变化。需要六个对象:AudioPlayer → Wire → AudioEmitter(以 3D 部件为父级),以及 AudioListener → Wire → AudioDeviceOutput(位于 SoundService 下)。将 SoundService.ListenerLocation 设为 Character 或 Camera(设置后,运行时引擎会在 SoundService 下自动创建 AudioDeviceOutput)。
--!strict
local SoundService = game:GetService("SoundService")
SoundService.ListenerLocation = Enum.ListenerLocation.Camera -- or Character
-- On the 3D part that should emit audio:
local part = workspace:WaitForChild("NoisyPart")
local player = Instance.new("AudioPlayer")
player.AssetId = "rbxassetid://YOUR_AUDIO_ID"
player.Looping = true
player.Parent = part
local emitter = Instance.new("AudioEmitter")
-- Custom curve: DistanceAttenuation is a NumberSequence (x = distance studs, y = volume 0..1).
-- This curve is only used when DistanceAttenuationMode == Custom (the default).
emitter.DistanceAttenuation = NumberSequence.new({
NumberSequenceKeypoint.new(0, 1), -- full volume at 0 studs
NumberSequenceKeypoint.new(50, 0.5), -- half volume at 50 studs
NumberSequenceKeypoint.new(70, 0), -- silent at 70 studs
})
-- Preset alternative (no custom curve needed):
-- emitter.DistanceAttenuationMode = Enum.DistanceAttenuationMode.Inverse
-- emitter.DistanceAttenuationBounds = NumberRange.new(4, 10000) -- [min,max] for the preset rolloff
emitter.Parent = part
local wire = Instance.new("Wire")
wire.SourceInstance = player
wire.TargetInstance = emitter
wire.Parent = part
player:Play()
发射器的父级位置决定音频从何处发出。AudioEmitter 会忽略自身朝向;旋转父级部件 / 附件来调整发射方向。
距离模型:AudioEmitter.DistanceAttenuationMode 用于选择衰减公式(默认为 Custom;使用你的 DistanceAttenuation 曲线;其他预设使用默认值为 [4, 10000] 的 DistanceAttenuationBounds,并忽略自定义曲线)。即使当前启用的是预设,GetDistanceAttenuation() 也始终返回自定义曲线。不要假设它反映了实际可听到的衰减,除非 Mode == Custom。只有在 Mode == Custom 时,SetDistanceAttenuation(curve) 才会影响播放。使用 SetAngleAttenuation({[angle]=volume}) 设置角度衰减(0–180° → 0–1);可用于定向音源(例如,化身语音向前方传播)。
**声学模拟(遮挡 / 衍射 / 混响):**启用 SoundService.AcousticSimulationEnabled,并在发射器和监听器上都启用 AcousticSimulationEnabled。当前参考文档不再提供各实例单独的 OcclusionEnabled、DiffractionEnabled 和 ReverbEnabled 开关;请勿生成对这些开关的调用。使用 emitter:GetAudibilityFor(listener) 或 listener:GetAudibilityFor(emitter) 获取结合了距离和角度衰减的值(0–1)。
监听器位置
SoundService.ListenerLocation(一个 ListenerLocation 枚举)用于控制自动创建 AudioListener 的位置:
- Default:在带语音聊天的体验中,位于摄像机处。
- None:不自动创建监听器;通过脚本创建。
- Character:以本地玩家的角色(
Humanoid.RootPart)为父级。 - Camera:以
workspace.CurrentCamera为父级。
设为 Character 或 Camera 时,运行时引擎会在 SoundService 下自动创建 AudioDeviceOutput。AudioListener 会根据距离和发射器的 DistanceAttenuation 曲线接收来自 AudioEmitter 的音频。
从脚本触发音频
local audio = script.Parent :: AudioPlayer
someEvent:Connect(function()
audio:Play()
end)
AudioPlayer:Play(atTime?)、:Stop(atTime?)。提供 atTime 时,操作会根据 SoundService:GetMixerTime() 进行调度,实现采样精确、与帧率无关的计时(节奏游戏/节拍同步)。:Cancel(actionId) 可取消计划在未来执行的 Play/Stop(取消成功时返回 true)。:Pause()、:SeekTime(...)、:GetWaveform(timeRange)(采样音量但不播放;适用于波形可视化,与实时 AudioAnalyzer 相比)。AudioPlayer.TimeVolume 可进行补间。有关音量和效果参数的补间,请参阅 references/audio-effects.md。
预加载音频
在需要使用主要音频资源之前(例如加载画面、回合开始时)预先加载,以避免低端设备首次播放时出现卡顿:
--!strict
local ContentProvider = game:GetService("ContentProvider")
local audioPlayer = workspace:WaitForChild("MusicPlayer") :: AudioPlayer
ContentProvider:PreloadAsync({ audioPlayer })
对于旧版 Sound 系统,以相同方式预加载 Sound 实例。
性能限制
- 并发声部(同时播放的音频流)数量有限制;上限因设备而异。移动设备的上限远低于桌面设备。
- 效果会占用 CPU,每条经过效果处理的活动音频流都会产生开销。混响和声学模拟的开销最大。
- 声学模拟(
SoundService.AcousticSimulationEnabled)会增加每个发声器的遮挡/绕射/混响开销;在低端客户端上或不需要时请将其禁用。 - 移动设备节流: 引擎可能会在内存较少的客户端上丢弃或降低音频效果的质量(例如,旧款手机上会丢弃翻页动画;部分音频效果也会受到相同影响)。请在低画质设置下进行测试。
AudioAnalyzer仅用于检查;不要在不必要时将其串接到可听音频路径中。
使用 MicroProfiler 分析音频(音频会显示在工作线程下),并查看 Developer Console 的 Memory 选项卡。
脚本上下文(客户端与服务端)
- 播放
AudioPlayer、Sound和效果是在客户端执行的。每个客户端都会播放自己的音频。服务端不会为客户端混音。 - 复制: 如果
AudioPlayer实例位于可复制的位置,其状态(播放/暂停/停止)会从服务端复制到客户端,但每个客户端的音量和效果都是本地的。对于一次性音效,建议采用客户端权威的触发方式:服务端通过 RemoteEvent 发送“事件已发生”的信号,由每个受影响的客户端在本地播放声音。这样可以避免复制每次触发的时间信息,并遵循各客户端的画质设置(与 VFX 的做法相同;请参阅 roblox-vfx skill)。 - 需要在所有客户端间同步的音乐/环境音可以由服务端驱动(
AudioPlayer位于ReplicatedStorage或SoundService中,由服务端调用:Play()),但请注意,每个客户端仍会在本地渲染,且可能出现不同步。 AudioDeviceInput(麦克风)仅限客户端使用。它会采集本地玩家的麦克风输入。可搭配VoiceChatService实现空间语音。访问控制:SetUserIdAccessList(userIds)+AccessType(Allow= 仅列表中的用户能听到输入,Deny= 除列表中的用户外所有人都能听到;默认值为Deny),GetUserIdAccessList()会返回允许/拒绝列表。- 切勿信任客户端的音频状态来判断游戏逻辑。 客户端声称“我播放了装填音效”并不具有任何权威性;请在服务端验证游戏效果(请参阅 roblox-networking)。
音频资源权限
- 2022 年音频隐私变更前上传的音频资源可能是私有的或用途受限。上传到你自己的体验中的资源可供该体验使用。
- Creator Store 提供可免费使用的音频资源库。这些资源可在任何体验中通过资源 ID 安全引用。
- 其他创作者上传的音频在其标记为公开使用之前,可能无法用于你的体验。如果引用第三方音频资源 ID 后无法播放,通常是权限问题。
- 如需使用新音频,请通过 Creator Dashboard 的资源管理器或 Open Cloud Assets API 上传(以编程方式上传请参阅 roblox-open-cloud skill)。
文本转语音(TTS)
AudioTextToSpeech 可将文本(每次请求不超过 300 个字符)转换为合成人声。可用的 VoiceId 值为:1–11(英语变体)、101–102(西班牙语)、201–202(德语)、301–302(意大利语)、401–402(法语)、501–502(中文普通话)、601–602(印地语)、701–702(日语)、801–802(阿拉伯语)、901–902(韩语)和 1001–1002(葡萄牙语);在各语言对应的语音配对中,奇数 ID 为男性,偶数 ID 为女性。连接方式与 AudioPlayer 类似:对于 2D 音频,使用 AudioTextToSpeech → Wire → AudioDeviceOutput;对于 3D 音频,使用 AudioTextToSpeech → Wire → AudioEmitter(并连接 listener→output)。在 AudioTextToSpeech 上设置 Text、VoiceId 和 Volume。:WaitForSpeechReady() 会一直等待,直到 AssetFetchStatus 为 Success(或 Failure)。所有文本都必须符合 Roblox 社区标准和使用条款。
音频分析: AudioAnalyzer 窗口由 AudioWindowSize 控制。Small(延迟最低、低频率分辨率)、Medium(均衡)、Large(分辨率最高、延迟较高)。
适用场景:无障碍功能(朗读 UI 文本)、无需录制音频的 NPC 配音、动态公告。
语音转文本(STT)
AudioSpeechToText 可将 AudioDeviceInput 捕获的语音转换为文本。需要将 VoiceChatService.UseAudioApi 设为 Enabled。连接方式:AudioDeviceInput → Wire → AudioSpeechToText。运行时设置 audioDeviceInput.Player = Players.LocalPlayer,即可将目标设为本地玩家的麦克风。Roblox 会自动检测说话者所用的语言(支持 17 种:阿拉伯语、简体中文/繁体中文、英语、法语、德语、印度尼西亚语、意大利语、日语、韩语、波兰语、葡萄牙语、西班牙语、俄语、土耳其语、泰语、越南语)。
若要使用 STT 而不向其他玩家广播语音,请禁用 VoiceChatService.EnableDefaultVoice。AudioSpeechToText 的所有音频都必须符合社区标准和使用条款。
最佳实践
- 预加载重要音频(音乐、常见音效),并在加载期间完成。一次性 UI 音效可以延迟加载。
- 循环播放环境音/音乐时,使用
Looping = true(音频图)或Looped = true(旧版)。若要循环播放有限的 N 次,可使用DidLoop事件(旧版Sound),或在音频图中统计播放次数。 - 淡入/淡出时,可通过补间调整
AudioPlayer.Volume(音频图)或Sound.Volume(旧版)。AudioFader是音频图原生的方式,可一次控制多个流的音量。 - **音乐与音效:**将音乐和音效分别路由到不同的
AudioFader或SoundGroup,以便单独静音音乐并应用闪避(音效通过AudioCompressor侧链降低音乐音量)。 - **3D 与 2D:**如果声音有世界位置,请使用 3D(
AudioEmitter);如果用于 UI/全局播放,请使用 2D(直接连接AudioDeviceOutput)。 - **无障碍功能:**为重要文本提供 TTS,为 VO 提供字幕选项,并且绝不要将音频作为游戏关键资讯的唯一提示方式。
- **移动设备:**在低画质下进行测试。引擎可能会舍弃特效;请确保不使用这些特效时,体验仍然可用。
- **并发播放:**频繁播放一次性音效时,应复用
AudioPlayer/Sound实例,而不是每次播放都创建并销毁实例。
常见错误
- 在新项目中使用
Sound/SoundGroup/SoundEffect,而音频图才是推荐方案。 - 将
AudioEmitter设为SoundService的子级(3D 音频必须将其设为 3D 零件/附件的子级)。 - 忘记添加
Wire(音频无法从播放器传到输出设备/发射器)。 - 误以为
SoundService.AmbientReverb会影响音频图(它只影响旧版Sound)。 - 将
DistanceAttenuation设为单个数值,而不是NumberSequence(它是曲线,不是标量)。 - 将客户端音频状态用于游戏逻辑(如重新加载音效、命中音效),而不是通过服务器验证。
- 未预加载,导致移动设备上首次播放时卡顿。
- 将第三方音频的资产 ID 写死;这些音频可能受到权限限制。
脚本
scripts/AudioBus.lua:一个简易的音乐/音效总线辅助工具,使用AudioFader控制组音量,并在音效播放时降低音乐音量。可根据你的混音需求进行调整。
如何进行
- 选择系统:新项目或复杂工作使用 graph,简单项目或旧项目使用
Sound。 - 布置总线(音乐、SFX、VO),并通过
AudioFader或SoundGroup进行路由。 - 在需要发声的部件上放置 3D 发声器;为每个发声器设置
DistanceAttenuation。 - 在能提升效果的地方添加音效(洞穴中的混响、水下的闷音、闪避)。
- 预加载,然后从事件触发(动画标记、UI、游戏玩法)。
- 在目标设备中性能最低的设备上,分析并发语音数和效果开销。
- 确认任何第三方音频资源的使用权限。
参考索引
- audio-effects.md:路由效果、混合音频总线、闪避音乐或调整衰减。
- audio-graph-vs-sound.md:选择音频系统或迁移旧版 Sound 代码。
声学 API 参考:https://create.roblox.com/docs/reference/engine/classes/AudioEmitter 和 https://create.roblox.com/docs/reference/engine/classes/AudioListener。