Laya.SoundManager 使用指南
简介
Laya.SoundManager 是 LayaAir 引擎的 声音管理类,用于控制背景音乐和音效的播放。引擎提供两种默认声音方案:WebAudio 和 H5Audio。
声音方案说明:
- 音效播放:优先使用 WebAudio,如不可用则使用 H5Audio
- 背景音乐:使用 H5Audio(WebAudio 会增加内存占用且需要等待加载完成)
- 推荐格式:背景音乐使用 mp3,音效使用 wav 或 mp3(打包 APP 时音效只能用 wav)
继承关系:
Laya.SoundManager(静态类,无需实例化)
目录
API 参考
音量属性
| 属性 |
类型 |
默认值 |
说明 |
musicVolume |
number |
1.0 |
背景音乐音量(0~1) |
soundVolume |
number |
1.0 |
音效音量(0~1) |
静音属性
| 属性 |
类型 |
默认值 |
说明 |
muted |
boolean |
false |
全部静音(音乐+音效) |
musicMuted |
boolean |
false |
背景音乐静音 |
soundMuted |
boolean |
false |
音效静音 |
静态属性
| 属性 |
类型 |
默认值 |
说明 |
playbackRate |
number |
1.0 |
声音播放速率 |
useAudioMusic |
boolean |
true |
背景音乐是否使用 Audio 标签 |
autoStopMusic |
boolean |
true |
失去焦点后是否自动停止背景音乐 |
播放方法
| 方法 |
参数 |
返回值 |
说明 |
playMusic(url, loops?, complete?, startTime?) |
地址, 循环次数, 回调, 起始时间 |
SoundChannel |
播放背景音乐(同时只能有一个) |
playSound(url, loops?, complete?, startTime?) |
地址, 循环次数, 回调, 起始时间 |
SoundChannel |
播放音效(可同时播放多个) |
停止方法
| 方法 |
参数 |
返回值 |
说明 |
stopMusic() |
- |
void |
停止背景音乐 |
stopSound(url) |
声音地址 |
void |
停止指定声音 |
stopAllSound() |
- |
void |
停止所有音效 |
stopAll() |
- |
void |
停止所有声音(音乐+音效) |
工具方法
| 方法 |
参数 |
返回值 |
说明 |
findChannel(url) |
声音地址 |
SoundChannel | null |
查找声音通道 |
setMusicVolume(volume) |
音量值(0~1) |
void |
设置背景音乐音量(已废弃) |
setSoundVolume(volume, url?) |
音量值, 地址 |
void |
设置音效音量(已废弃) |
基础用法
1. 播放背景音乐
Laya.SoundManager.playMusic("res/music/bgm.mp3");
Laya.SoundManager.playMusic("res/music/bgm.mp3", 0);
Laya.SoundManager.playMusic("res/music/bgm.mp3", 1, (success: boolean) => {
console.log("音乐播放完成:", success);
});
Laya.SoundManager.playMusic("res/music/bgm.mp3", 1, null, 10);
2. 播放音效
Laya.SoundManager.playSound("res/sounds/click.mp3");
Laya.SoundManager.playSound("res/sounds/loop.wav", 0);
Laya.SoundManager.playSound("res/sounds/explosion.mp3", 1, () => {
console.log("音效播放完成");
});
3. 控制音量
Laya.SoundManager.musicVolume = 0.5;
Laya.SoundManager.soundVolume = 0.8;
console.log("音乐音量:", Laya.SoundManager.musicVolume);
console.log("音效音量:", Laya.SoundManager.soundVolume);
4. 静音控制
Laya.SoundManager.muted = true;
Laya.SoundManager.musicMuted = true;
Laya.SoundManager.soundMuted = true;
Laya.SoundManager.muted = false;
5. 停止播放
Laya.SoundManager.stopMusic();
Laya.SoundManager.stopSound("res/sounds/click.mp3");
Laya.SoundManager.stopAllSound();
Laya.SoundManager.stopAll();
实用示例
示例1: 基础音效播放器
@regClass()
export class SoundPlayer extends Laya.Script {
public playClick(): void {
Laya.SoundManager.playSound("res/sounds/click.mp3");
}
public playButtonDown(): void {
Laya.SoundManager.playSound("res/sounds/button_down.mp3");
}
public playButtonUp(): void {
Laya.SoundManager.playSound("res/sounds/button_up.mp3");
}
public playBGM(): void {
Laya.SoundManager.playMusic("res/music/bgm.mp3", 0);
}
public stopBGM(): void {
Laya.SoundManager.stopMusic();
}
}
示例2: 游戏音效管理器
@regClass()
export class GameSoundManager extends Laya.Script {
private static instance: GameSoundManager = null;
private bgmVolume: number = 0.6;
private sfxVolume: number = 0.8;
static getInstance(): GameSoundManager {
if (!this.instance) {
this.instance = new GameSoundManager();
}
return this.instance;
}
onAwake(): void {
this.init();
}
private init(): void {
Laya.SoundManager.musicVolume = this.bgmVolume;
Laya.SoundManager.soundVolume = this.sfxVolume;
}
public playBGM(url: string): void {
Laya.SoundManager.playMusic(url, 0);
}
public stopBGM(): void {
Laya.SoundManager.stopMusic();
}
public playSFX(url: string): void {
Laya.SoundManager.playSound(url);
}
public setMusicVolume(volume: number): void {
this.bgmVolume = Math.max(0, Math.min(1, volume));
Laya.SoundManager.musicVolume = this.bgmVolume;
}
public setSFXVolume(volume: number): void {
this.sfxVolume = Math.max(0, Math.min(1, volume));
Laya.SoundManager.soundVolume = this.sfxVolume;
}
public muteAll(): void {
Laya.SoundManager.muted = true;
}
public unmuteAll(): void {
Laya.SoundManager.muted = false;
Laya.SoundManager.musicVolume = this.bgmVolume;
Laya.SoundManager.soundVolume = this.sfxVolume;
}
}
let soundMgr = GameSoundManager.getInstance();
soundMgr.playBGM("res/music/battle.mp3");
soundMgr.playSFX("res/sounds/sword.mp3");
示例3: 音量设置面板
@regClass()
export class VolumePanel extends Laya.Sprite {
private musicSlider: Laya.Sprite;
private sfxSlider: Laya.Sprite;
private muteBtn: Laya.Sprite;
constructor() {
super();
this.setupUI();
}
private setupUI(): void {
this.musicSlider = this.createSlider("音乐音量", 0.6, (value: number) => {
Laya.SoundManager.musicVolume = value;
});
this.musicSlider.pos(20, 20);
this.addChild(this.musicSlider);
this.sfxSlider = this.createSlider("音效音量", 0.8, (value: number) => {
Laya.SoundManager.soundVolume = value;
});
this.sfxSlider.pos(20, 80);
this.addChild(this.sfxSlider);
this.muteBtn = this.createButton("静音");
this.muteBtn.pos(20, 140);
this.muteBtn.on(Laya.Event.CLICK, this, this.toggleMute);
this.addChild(this.muteBtn);
}
private toggleMute(): void {
Laya.SoundManager.muted = !Laya.SoundManager.muted;
let label = this.muteBtn.getChildAt(0) as Laya.Text;
label.text = Laya.SoundManager.muted ? "取消静音" : "静音";
}
private createSlider(label: string, value: number, callback: (value: number) => void): Laya.Sprite {
let container = new Laya.Sprite();
let text = new Laya.Text();
text.text = label + ": " + Math.floor(value * 100) + "%";
text.fontSize = 16;
text.color = "#FFFFFF";
container.addChild(text);
let bg = new Laya.Sprite();
bg.graphics.drawRect(0, 0, 200, 10, "#666666");
bg.pos(0, 25);
container.addChild(bg);
let fill = new Laya.Sprite();
fill.graphics.drawRect(0, 0, 200 * value, 10, "#00FF00");
fill.pos(0, 25);
container.addChild(fill);
return container;
}
private createButton(label: string): Laya.Sprite {
let btn = new Laya.Sprite();
btn.graphics.drawRect(0, 0, 100, 40, "#4488FF");
btn.size(100, 40);
let text = new Laya.Text();
text.text = label;
text.fontSize = 16;
text.color = "#FFFFFF";
text.pos(35, 10);
btn.addChild(text);
return btn;
}
}
示例4: 战斗音效系统
@regClass()
export class BattleSoundSystem extends Laya.Script {
public preloadSounds(): void {
let sounds = [
"res/sounds/attack.mp3",
"res/sounds/hit.mp3",
"res/sounds/die.mp3",
"res/sounds/skill.mp3",
"res/sounds/victory.mp3",
"res/sounds/defeat.mp3"
];
for (let sound of sounds) {
Laya.SoundManager.playSound(sound, 0);
Laya.SoundManager.stopSound(sound);
}
}
public playAttack(): void {
Laya.SoundManager.playSound("res/sounds/attack.mp3");
}
public playHit(): void {
Laya.SoundManager.playSound("res/sounds/hit.mp3");
}
public playDie(): void {
Laya.SoundManager.playSound("res/sounds/die.mp3");
}
public playSkill(skillId: number): void {
let soundUrl = "res/sounds/skill" + skillId + ".mp3";
Laya.SoundManager.playSound(soundUrl);
}
public playVictory(): void {
Laya.SoundManager.stopMusic();
Laya.SoundManager.playMusic("res/sounds/victory.mp3", 0);
}
public playDefeat(): void {
Laya.SoundManager.stopMusic();
Laya.SoundManager.playMusic("res/sounds/defeat.mp3", 0);
}
public stopBattleSounds(): void {
Laya.SoundManager.stopAllSound();
}
}
示例5: 场景音效切换
@regClass()
export class SceneSoundManager extends Laya.Script {
private currentBGM: string = "";
public switchToMainMenu(): void {
this.playBGM("res/music/main_menu.mp3");
}
public switchToBattle(): void {
this.playBGM("res/music/battle.mp3");
}
public switchToVillage(): void {
this.playBGM("res/music/village.mp3");
}
private playBGM(url: string): void {
if (this.currentBGM === url) return;
this.currentBGM = url;
Laya.SoundManager.playMusic(url, 0);
}
public fadeInBGM(url: string, duration: number = 1): void {
Laya.SoundManager.musicVolume = 0;
Laya.SoundManager.playMusic(url, 0);
let step = 0.1;
let interval = duration * 1000 / 10;
let count = 0;
let totalSteps = 10;
Laya.timer.loop(interval, this, this.onFadeInTick);
this._fadeInStep = step;
this._fadeInTotalSteps = totalSteps;
this._fadeInCount = 0;
}
private _fadeInStep: number = 0.1;
private _fadeInTotalSteps: number = 10;
private _fadeInCount: number = 0;
private onFadeInTick(): void {
this._fadeInCount++;
let newVolume = Laya.SoundManager.musicVolume + this._fadeInStep;
if (this._fadeInCount >= this._fadeInTotalSteps || newVolume >= 0.6) {
newVolume = 0.6;
Laya.timer.clear(this, this.onFadeInTick);
}
Laya.SoundManager.musicVolume = newVolume;
}
public fadeOutBGM(duration: number = 1): void {
let step = 0.1;
let interval = duration * 1000 / 10;
let count = 0;
let totalSteps = 10;
Laya.timer.loop(interval, this, this.onFadeOutTick);
this._fadeOutStep = step;
this._fadeOutTotalSteps = totalSteps;
this._fadeOutCount = 0;
}
private _fadeOutStep: number = 0.1;
private _fadeOutTotalSteps: number = 10;
private _fadeOutCount: number = 0;
private onFadeOutTick(): void {
this._fadeOutCount++;
let newVolume = Laya.SoundManager.musicVolume - this._fadeOutStep;
if (this._fadeOutCount >= this._fadeOutTotalSteps || newVolume <= 0) {
newVolume = 0;
Laya.SoundManager.stopMusic();
Laya.timer.clear(this, this.onFadeOutTick);
}
Laya.SoundManager.musicVolume = newVolume;
}
}
高级技巧
1. 使用 SoundChannel 控制声音
let channel = Laya.SoundManager.playSound("res/sounds/loop.mp3", 0);
if (channel) {
channel.pause();
channel.resume();
channel.stop();
channel.volume = 0.5;
console.log("播放位置:", channel.position);
console.log("总时长:", channel.duration);
}
2. 查找并控制正在播放的声音
let channel = Laya.SoundManager.findChannel("res/sounds/explosion.mp3");
if (channel) {
console.log("音效正在播放");
channel.stop();
} else {
console.log("音效未播放");
Laya.SoundManager.playSound("res/sounds/explosion.mp3");
}
3. 播放速率控制
Laya.SoundManager.playbackRate = 1.5;
Laya.SoundManager.playbackRate = 0.8;
Laya.SoundManager.playbackRate = 1.0;
4. 失去焦点处理
Laya.SoundManager.autoStopMusic = true;
Laya.SoundManager.autoStopMusic = false;
Laya.stage.on(Laya.Event.BLUR, this, () => {
console.log("失去焦点");
});
Laya.stage.on(Laya.Event.FOCUS, this, () => {
console.log("获得焦点");
if (!Laya.SoundManager.autoStopMusic) {
Laya.SoundManager.playMusic("res/music/bgm.mp3", 0);
}
});
5. 条件音效播放
@regClass()
export class ConditionalSound extends Laya.Script {
public playSoundSafe(url: string): void {
if (!this.enabled) return;
if (Laya.SoundManager.soundMuted) return;
Laya.SoundManager.playSound(url);
}
public playRandomSound(baseName: string, count: number): void {
if (!this.enabled) return;
let index = Math.floor(Math.random() * count);
let url = "res/sounds/" + baseName + index + ".mp3";
Laya.SoundManager.playSound(url);
}
}
最佳实践
1. 音量设置建议
| 场景 |
音乐音量 |
音效音量 |
| 主菜单 |
0.6~0.8 |
0.8~1.0 |
| 战斗中 |
0.4~0.6 |
0.8~1.0 |
| 剧情对话 |
0.3~0.5 |
0.6~0.8 |
2. 音效格式选择
Laya.SoundManager.playMusic("res/music/bgm.mp3");
Laya.SoundManager.playSound("res/sounds/click.wav");
3. 音效预加载
@regClass()
export class SoundPreloader extends Laya.Script {
public preloadCommonSounds(): void {
let commonSounds = [
"res/sounds/click.mp3",
"res/sounds/close.mp3",
"res/sounds/open.mp3",
"res/sounds/confirm.mp3",
"res/sounds/cancel.mp3"
];
for (let sound of commonSounds) {
let channel = Laya.SoundManager.playSound(sound);
if (channel) {
channel.stop();
}
}
}
onAwake(): void {
this.preloadCommonSounds();
}
}
4. 音量持久化
@regClass()
export class SoundSettings extends Laya.Script {
private static readonly MUSIC_VOLUME_KEY = "musicVolume";
private static readonly SFX_VOLUME_KEY = "sfxVolume";
private static readonly MUTED_KEY = "soundMuted";
public static saveSettings(): void {
Laya.LocalStorage.setItem(this.MUSIC_VOLUME_KEY, Laya.SoundManager.musicVolume.toString());
Laya.LocalStorage.setItem(this.SFX_VOLUME_KEY, Laya.SoundManager.soundVolume.toString());
Laya.LocalStorage.setItem(this.MUTED_KEY, Laya.SoundManager.muted.toString());
}
public static loadSettings(): void {
let musicVol = Laya.LocalStorage.getItem(this.MUSIC_VOLUME_KEY);
let sfxVol = Laya.LocalStorage.getItem(this.SFX_VOLUME_KEY);
let muted = Laya.LocalStorage.getItem(this.MUTED_KEY);
if (musicVol) Laya.SoundManager.musicVolume = parseFloat(musicVol);
if (sfxVol) Laya.SoundManager.soundVolume = parseFloat(sfxVol);
if (muted) Laya.SoundManager.muted = muted === "true";
}
}
5. 性能优化
onUpdate(): void {
Laya.SoundManager.playSound("res/sounds/loop.mp3");
}
private isPlaying: boolean = false;
playLoopSound(): void {
if (!this.isPlaying) {
Laya.SoundManager.playSound("res/sounds/loop.mp3", 0);
this.isPlaying = true;
}
}
onDestroy(): void {
Laya.SoundManager.stopAllSound();
Laya.SoundManager.stopMusic();
}
6. 调试技巧
function debugSoundManager(): void {
console.log("=== SoundManager 状态 ===");
console.log("音乐音量:", Laya.SoundManager.musicVolume);
console.log("音效音量:", Laya.SoundManager.soundVolume);
console.log("全部静音:", Laya.SoundManager.muted);
console.log("音乐静音:", Laya.SoundManager.musicMuted);
console.log("音效静音:", Laya.SoundManager.soundMuted);
console.log("播放速率:", Laya.SoundManager.playbackRate);
console.log("自动停止音乐:", Laya.SoundManager.autoStopMusic);
}
let testSounds: string[] = [];
let testIndex: number = 0;
function testAllSounds(): void {
testSounds = [
"res/sounds/click.mp3",
"res/sounds/hit.mp3",
"res/sounds/explosion.mp3"
];
testIndex = 0;
Laya.timer.loop(1000, this, onTestTick);
}
function onTestTick(): void {
if (testIndex < testSounds.length) {
Laya.SoundManager.playSound(testSounds[testIndex]);
console.log("测试音效:", testSounds[testIndex]);
testIndex++;
} else {
Laya.timer.clear(this, onTestTick);
}
}
注意事项
- 自动停止:默认情况下失去焦点会自动停止背景音乐(
autoStopMusic = true)
- 音乐独占:同时只能有一个背景音乐在播放,新的音乐会替换旧的
- 音效并发:音效可以同时播放多个,注意控制数量避免性能问题
- 循环参数:
loops = 0 表示无限循环,loops = 1 表示播放一次
- 完成回调:背景音乐的完成回调参数
success 为 true 表示播放完成,false 表示被停止
- 音量范围:音量值范围为
0(静音)到 1(最大音量)
- 平台兼容:打包 APP 时音效建议使用 wav 格式
- 资源释放:使用
stopAll() 后音频资源仍会被缓存,下次播放时直接使用缓存
相关文档
所有评论(0)