Files
mp-xieyingeng/assets/scripts/utils/AudioManager.ts
2026-06-29 19:55:40 +08:00

85 lines
2.4 KiB
TypeScript

import { AudioClip, AudioSource, Node } from 'cc';
/**
* 音效管理器
* 统一管理全局按钮点击等通用音效,避免页面各自维护 AudioSource。
*/
export class AudioManager {
private static _instance: AudioManager | null = null;
private _clickAudio: AudioClip | null = null;
private _hostNode: Node | null = null;
private _audioSource: AudioSource | null = null;
private _pausedAudioSources: AudioSource[] = [];
static get instance(): AudioManager {
if (!this._instance) {
this._instance = new AudioManager();
}
return this._instance;
}
private constructor() {}
init(clickAudio: AudioClip | null, hostNode: Node | null): void {
this._clickAudio = clickAudio;
this._hostNode = hostNode;
this._audioSource = null;
}
playButtonClick(): void {
this._playOneShot(this._clickAudio);
}
pausePlayingAudioSources(): void {
if (!this._hostNode?.isValid) {
return;
}
this._pausedAudioSources = [];
const audioSources = this._hostNode.getComponentsInChildren(AudioSource);
audioSources.forEach((audioSource) => {
if (!audioSource?.isValid || !audioSource.playing) {
return;
}
audioSource.pause();
this._pausedAudioSources.push(audioSource);
});
}
resumePausedAudioSources(): void {
const pausedAudioSources = this._pausedAudioSources;
this._pausedAudioSources = [];
pausedAudioSources.forEach((audioSource) => {
if (audioSource?.isValid && !audioSource.playing) {
audioSource.play();
}
});
}
private _playOneShot(clip: AudioClip | null): void {
if (!clip) {
return;
}
const audioSource = this._ensureAudioSource();
audioSource?.playOneShot(clip);
}
private _ensureAudioSource(): AudioSource | null {
if (this._audioSource?.isValid) {
return this._audioSource;
}
if (!this._hostNode?.isValid) {
console.warn('[AudioManager] 未初始化宿主节点,无法播放音效');
return null;
}
this._audioSource = this._hostNode.getComponent(AudioSource) ?? this._hostNode.addComponent(AudioSource);
return this._audioSource;
}
}