感谢您的反馈!
Cocos2.X开发的小游戏,在淘宝环境运行时使用cc.audioEngine播放音频和音效,无法正常使用uncache/uncacheAll销毁音频实例。依赖音效较多时,会有较大概率连续报错(见下图),造成游戏卡顿的客诉。
使用以下《音频管理器》章节的代码片段作为基础,自行实现单例音频管理器,替换AudioEngine使用。
const interval = 180; const preload = 5; export class SoundMgr { /** * 音乐和单次音效播放 */ private _audioComp: cc.AudioSource = new cc.AudioSource(); /** * 循环音效播放 */ private _audioPool: cc.AudioSource[] = []; private _clipTime: Map<cc.AudioClip, number> = new Map() /** 用于挂载的组件 */ private _soundNode = null; constructor() { this._soundNode = new cc.Node(); cc.game.addPersistRootNode(this._soundNode); for (let i = 0; i < preload; i++) { const audio = this._soundNode.addComponent(cc.AudioSource); this._audioPool.push(audio); } } public play(audioClip: cc.AudioClip, isLoop: boolean = true) { let clip = audioClip; if (!clip) return; this._audioComp.clip = clip; this._audioComp.loop = isLoop; this._audioComp.play(); } public stop() { this._audioComp.stop(); } public setVolume(volume: number) { this._audioComp.volume = volume; } private getAudio(): cc.AudioSource { let audio: cc.AudioSource if (this._audioPool.length === 0) { audio = this._soundNode.addComponent(cc.AudioSource); } else { audio = this._audioPool.pop(); } return audio; } private putAudio(audio: cc.AudioSource) { // @ts-ignore audio.clip.src = null; this._audioPool.push(audio); } /** * @en : play effect once * @zh : 播放一次特效 * @param {string} audioClip * @param {*} volume */ public playEffect(audioClip: cc.AudioClip, volume = 0.5) { let clip = audioClip; if (!clip) return; const lastTime = this._clipTime.get(clip) || 0; const currentTime = cc.director.getTotalTime(); /* if interval is too low, return it for performance */ if ((currentTime - lastTime) < interval) { return; } this._clipTime.set(clip, currentTime); const audio = this.getAudio(); audio.clip = clip; audio.play(); const audioDuration = audio.getDuration(); setTimeout(() => { if (this._audioPool.length >= preload) { audio.destroy(); } else { this.putAudio(audio); } }, audioDuration * 1000) } } const SOUND = new SoundMgr(); export default SOUND;
import SOUND from "../frame/SoundMgr"; import RES from "../frame/ResMgr"; const { ccclass, property } = cc._decorator; @ccclass export default class play extends cc.Component { @property(cc.Slider) volume: cc.Slider = null; protected onEnable(): void { this.volume.node.on('slide', this.callback, this); } protected onDisable(): void { this.volume.node.off('slide', this.callback, this); } callback(slider:cc.Slider) { SOUND.setVolume(slider.progress); } playBgm() { const clip = RES.getClip("bgm"); SOUND.play(clip,0.65); this.volume.progress = 0.65; } stopBgm() { SOUND.stop(); } playEffect() { const clip = RES.getClip("chick"); SOUND.playEffect(clip); } playEffect1() { const clip = RES.getClip("btn"); SOUND.playEffect(clip); } }