跳转到内容

音频

Estella 提供完整的音频系统,包含 ECS 组件、总线混音和空间音频。AudioPlugin 由引擎默认包含。

组件

AudioSource

附加到任意实体上播放音频。空间音频需要 Transform 组件。

属性类型默认值说明
clipstring''音频文件路径
busstring'sfx'音频总线:sfxmusicuivoice
volumenumber1.0音量(0–1)
pitchnumber1.0播放速率(0.1–3)
loopbooleanfalse循环播放
playOnAwakebooleanfalse实体加载时自动播放
spatialbooleanfalse启用空间音频
minDistancenumber100空间音频参考距离
maxDistancenumber1000空间音频最大距离
attenuationModelnumber10 = 线性, 1 = 反比, 2 = 指数
rolloffnumber1.0空间衰减因子(0–5)
prioritynumber0播放优先级
enabledbooleantrue组件激活

AudioListener

添加到摄像机或玩家实体上接收空间音频。同一时间只应有一个激活的监听器。

属性类型默认值说明
enabledbooleantrue监听器激活

快速播放 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 总线:

总线默认音量典型用途
sfx1.0音效:爆炸、脚步声、UI 点击、一次性音效
music0.8背景音乐和环境循环音
ui1.0UI 专用音效:按钮悬停、面板开关、通知音
voice1.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) — 音量在 minDistancemaxDistance 之间线性降低
  • 反比 (1, 默认) — 基于反比距离的真实衰减
  • 指数 (2) — 使用指数曲线的陡峭衰减

微信小游戏

在微信平台上,音频使用 wx.createInnerAudioContext() 而非 Web Audio API。主要差异:

  • 无混音器 — 总线音量控制(setMasterVolumesetSFXVolume 等)不可用。请使用 AudioHandle.setVolume() 进行逐个音效的音量控制。
  • 无立体声声像setPan() 无效。空间音频衰减仍然有效(基于音量)。
  • 本地文件路径 — 构建包内的音频文件通过相对路径访问(如 assets/sounds/bgm.mp3)。

编辑器集成

  • 检查器 — 音频文件显示内联预览播放器,支持播放/暂停控制
  • 拖拽到场景 — 从资产浏览器拖拽音频文件到场景中,自动创建带 AudioSource 的实体
  • Game View — Game View 工具栏中有静音切换按钮
  • Scene View — Scene View 中跳过音频系统,避免编辑时产生不必要的播放