音频
Estella 提供完整的音频系统,包含 ECS 组件、总线混音和空间音频。AudioPlugin 由引擎默认包含。
组件
AudioSource
附加到任意实体上播放音频。空间音频需要 Transform 组件。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
clip | string | '' | 音频文件路径 |
bus | string | 'sfx' | 音频总线:sfx、music、ui、voice |
volume | number | 1.0 | 音量(0–1) |
pitch | number | 1.0 | 播放速率(0.1–3) |
loop | boolean | false | 循环播放 |
playOnAwake | boolean | false | 实体加载时自动播放 |
spatial | boolean | false | 启用空间音频 |
minDistance | number | 100 | 空间音频参考距离 |
maxDistance | number | 1000 | 空间音频最大距离 |
attenuationModel | number | 1 | 0 = 线性, 1 = 反比, 2 = 指数 |
rolloff | number | 1.0 | 空间衰减因子(0–5) |
priority | number | 0 | 播放优先级 |
enabled | boolean | true | 组件激活 |
AudioListener
添加到摄像机或玩家实体上接收空间音频。同一时间只应有一个激活的监听器。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enabled | boolean | true | 监听器激活 |
快速播放 API
对于不需要实体的简单音效,使用静态 Audio 类:
import { Audio } from 'esengine';
// 播放音效const handle = Audio.playSFX('assets/explosion.mp3', { volume: 0.8, pitch: 1.2, pan: -0.5, // 立体声声像(-1 左, 0 中, 1 右)});
// 控制播放handle.pause();handle.resume();handle.stop();handle.setVolume(0.6);handle.setLoop(true);handle.setPlaybackRate(1.5);
// 查询状态console.log(handle.isPlaying, handle.currentTime, handle.duration);背景音乐
// 播放背景音乐,带淡入Audio.playBGM('assets/theme.mp3', { volume: 0.5, fadeIn: 2.0 });
// 切换背景音乐,带交叉淡入淡出(旧曲目淡出,新曲目同时淡入)Audio.playBGM('assets/boss.mp3', { volume: 0.7, crossFade: 1.5 });
// 停止背景音乐,带淡出Audio.stopBGM(1.0);
// 立即停止所有音频(背景音乐 + 取消淡入淡出)Audio.stopAll();AudioHandle
playSFX 和基于实体的播放都返回 AudioHandle:
| 方法 / 属性 | 说明 |
|---|---|
stop() | 停止播放并释放资源 |
pause() | 暂停播放 |
resume() | 恢复暂停的播放 |
setVolume(v) | 设置音量(0–1) |
setPan(p) | 设置立体声声像(-1 左, 0 中, 1 右) |
setLoop(l) | 启用/禁用循环 |
setPlaybackRate(r) | 设置播放速度 |
onEnd(cb) | 注册播放结束回调 |
isPlaying | 是否正在播放 |
currentTime | 当前播放位置(秒) |
duration | 总时长(秒) |
音频总线
每个音频都通过一个**总线(bus)**路由——即一个虚拟混音通道。引擎提供 4 个内置总线,全部连接到 master 总线:
| 总线 | 默认音量 | 典型用途 |
|---|---|---|
sfx | 1.0 | 音效:爆炸、脚步声、UI 点击、一次性音效 |
music | 0.8 | 背景音乐和环境循环音 |
ui | 1.0 | UI 专用音效:按钮悬停、面板开关、通知音 |
voice | 1.0 | 角色对话、旁白、配音 |
4 个总线行为完全一致——它们只是独立的音量/静音通道。这种分离让玩家可以在设置菜单中独立调节各类别音量(例如降低音乐但保持音效音量):
master (1.0)├── sfx (1.0)├── music (0.8)├── ui (1.0)└── voice (1.0)通过 AudioSource 组件的 bus 属性或 playSFX 配置设置总线。未指定时默认使用 sfx 总线。
音量控制
通过混音器按总线控制音量:
import { Audio } from 'esengine';
Audio.setMasterVolume(0.8);Audio.setMusicVolume(0.5);Audio.setSFXVolume(1.0);Audio.setUIVolume(0.7);
// 静音指定总线Audio.muteBus('music', true);预加载
预加载音频文件以避免首次播放延迟:
import { Audio } from 'esengine';
await Audio.preload('assets/explosion.mp3');await Audio.preloadAll([ 'assets/jump.mp3', 'assets/coin.mp3', 'assets/bgm.mp3',]);基于实体的播放
在编辑器中或通过代码为实体添加 AudioSource:
import { defineSystem, addSystem, Query, Mut, AudioSource } from 'esengine';
addSystem(defineSystem( [Query(Mut(AudioSource))], (query) => { for (const [entity, audio] of query) { // 运行时更改音频剪辑 audio.clip = 'assets/new-sound.mp3'; audio.volume = 0.5; } }));空间音频
在 AudioSource 上设置 spatial: true 并为摄像机实体添加 AudioListener 即可启用空间音频。
import { AudioSource, AudioListener, AttenuationModel } from 'esengine';系统会根据源实体和监听器实体的 Transform 位置自动计算基于距离的衰减和立体声声像。
衰减模型:
- 线性 (0) — 音量在
minDistance和maxDistance之间线性降低 - 反比 (1, 默认) — 基于反比距离的真实衰减
- 指数 (2) — 使用指数曲线的陡峭衰减
微信小游戏
在微信平台上,音频使用 wx.createInnerAudioContext() 而非 Web Audio API。主要差异:
- 无混音器 — 总线音量控制(
setMasterVolume、setSFXVolume等)不可用。请使用AudioHandle.setVolume()进行逐个音效的音量控制。 - 无立体声声像 —
setPan()无效。空间音频衰减仍然有效(基于音量)。 - 本地文件路径 — 构建包内的音频文件通过相对路径访问(如
assets/sounds/bgm.mp3)。
编辑器集成
- 检查器 — 音频文件显示内联预览播放器,支持播放/暂停控制
- 拖拽到场景 — 从资产浏览器拖拽音频文件到场景中,自动创建带
AudioSource的实体 - Game View — Game View 工具栏中有静音切换按钮
- Scene View — Scene View 中跳过音频系统,避免编辑时产生不必要的播放