mirror of
https://gitee.com/dgflash/oops-plugin-framework.git
synced 2026-05-07 19:07:30 +08:00
优化音乐模块分类功能
This commit is contained in:
@@ -87,10 +87,10 @@ export class AudioEffectPool {
|
||||
/**
|
||||
* 加载与播放音效
|
||||
* @param path 音效资源地址与音效资源
|
||||
* @param params 音效附加参数
|
||||
* @param params 音效附加参数
|
||||
* @returns
|
||||
*/
|
||||
async loadAndPlay(path: string | AudioClip, params?: IAudioParams): Promise<number> {
|
||||
async loadAndPlay(path: string | AudioClip, params?: IAudioParams): Promise<AudioEffect> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
if (params == null) {
|
||||
params = {
|
||||
@@ -102,28 +102,30 @@ export class AudioEffectPool {
|
||||
else {
|
||||
if (params.bundle == null) params.bundle = resLoader.defaultBundleName;
|
||||
if (params.loop == null) params.loop = false;
|
||||
if (params.type == null) params.type = AudioEffectType.Effect;
|
||||
if (params.type == null) params.type = AudioEffectType.Effect; // 默认音效类型
|
||||
}
|
||||
|
||||
let iad = this.data[params.type!];
|
||||
if (iad == null) console.error(`类型为【${params.type!}】的音效配置不存在`);
|
||||
|
||||
if (!iad.switch) return resolve(-1);
|
||||
if (!iad.switch) {
|
||||
resolve(null!);
|
||||
return;
|
||||
}
|
||||
|
||||
if (params.volume == null) params.volume = iad.volume;
|
||||
|
||||
let bundle = params.bundle!;
|
||||
|
||||
let key: string = null!;
|
||||
let clip: AudioClip | undefined;
|
||||
// 通过预制自动加载的音效资源(音效内存跟随预制体的内存一并释放)
|
||||
if (path instanceof AudioClip) {
|
||||
key = `${params.type}_${path.uuid}`;
|
||||
clip = path;
|
||||
key = path.uuid;
|
||||
}
|
||||
// 非引擎管理的远程资源加载
|
||||
else if (path.indexOf("http") == 0) {
|
||||
key = path;
|
||||
key = `${params.type}_${path}`;
|
||||
clip = this.res_remote.get(path);
|
||||
if (clip == null) {
|
||||
const extension = path.split('.').pop();
|
||||
@@ -133,7 +135,7 @@ export class AudioEffectPool {
|
||||
}
|
||||
// 资源加载
|
||||
else {
|
||||
key = `${bundle}_${path}`;
|
||||
key = `${params.type}_${bundle}_${path}`;
|
||||
clip = resLoader.get(path, AudioClip, bundle)!;
|
||||
|
||||
// 加载音效资源
|
||||
@@ -153,7 +155,7 @@ export class AudioEffectPool {
|
||||
|
||||
// 资源已被释放
|
||||
if (!clip.isValid) {
|
||||
resolve(-1);
|
||||
resolve(null!);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -177,8 +179,7 @@ export class AudioEffectPool {
|
||||
else {
|
||||
node = this.pool.get()!;
|
||||
ae = node.getComponent(AudioEffect)!;
|
||||
ae.key = ae.key;
|
||||
ae.aeid = ae.aeid;
|
||||
key = ae.key;
|
||||
}
|
||||
|
||||
// 记录正在播放的音效播放器
|
||||
@@ -189,41 +190,28 @@ export class AudioEffectPool {
|
||||
ae.volume = params.volume!;
|
||||
ae.clip = clip;
|
||||
ae.play();
|
||||
resolve(aeid);
|
||||
resolve(ae);
|
||||
});
|
||||
}
|
||||
|
||||
/** 音效播放完成 */
|
||||
private onAudioEffectPlayComplete(ae: AudioEffect) {
|
||||
const bundle = ae.params!.bundle!;
|
||||
this.put(ae.aeid, ae.path, bundle); // 播放完回收对象
|
||||
ae.params && ae.params.onPlayComplete && ae.params.onPlayComplete(ae.aeid, ae.path, bundle);
|
||||
this.put(ae);
|
||||
ae.params && ae.params.onPlayComplete && ae.params.onPlayComplete(ae);
|
||||
console.log(`【音效】回收,池中剩余音效播放器【${this.pool.size()}】`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 回收音效播放器
|
||||
* @param aeid 播放器编号
|
||||
* @param path 音效路径
|
||||
* @param bundleName 资源包名
|
||||
* @param ae loadAndPlay 方法返回的音效播放器对象
|
||||
*/
|
||||
put(aeid: number, path: string | AudioClip, bundleName: string = resLoader.defaultBundleName) {
|
||||
let key: string;
|
||||
if (path instanceof AudioClip) {
|
||||
key = path.uuid;
|
||||
}
|
||||
else if (path.indexOf("http") == 0) {
|
||||
key = path;
|
||||
}
|
||||
else {
|
||||
key = `${bundleName}_${path}`;
|
||||
}
|
||||
key += "_" + aeid;
|
||||
|
||||
let ae = this.effects.get(key);
|
||||
if (ae && ae.clip) {
|
||||
this.effects.delete(key);
|
||||
ae.stop();
|
||||
this.pool.put(ae.node);
|
||||
put(ae: AudioEffect) {
|
||||
let effect = this.effects.get(ae.key);
|
||||
if (effect && effect.clip) {
|
||||
effect.stop();
|
||||
effect.clip = null;
|
||||
this.effects.delete(ae.key);
|
||||
this.pool.put(effect.node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,13 +226,11 @@ export class AudioEffectPool {
|
||||
|
||||
/** 恢复所有音效 */
|
||||
play() {
|
||||
// if (!this.switch) return;
|
||||
this.effects.forEach(ae => ae.play());
|
||||
}
|
||||
|
||||
/** 暂停所有音效 */
|
||||
pause() {
|
||||
// if (!this.switch) return;
|
||||
this.effects.forEach(ae => {
|
||||
ae.pause();
|
||||
this.onAudioEffectPlayComplete(ae);
|
||||
@@ -252,6 +238,16 @@ export class AudioEffectPool {
|
||||
this.effects.clear();
|
||||
}
|
||||
|
||||
/** 施放音乐资源对象 */
|
||||
releaseAudioClip(ae: AudioEffect) {
|
||||
if (ae.path instanceof AudioClip) {
|
||||
ae.path.decRef();
|
||||
}
|
||||
else {
|
||||
resLoader.release(ae.path, ae.params!.bundle)
|
||||
}
|
||||
}
|
||||
|
||||
/** 释放所有音效资源与对象池中播放器 */
|
||||
release() {
|
||||
// 释放池中音乐播放器
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { AudioClip, Component } from "cc";
|
||||
import { oops } from "../../Oops";
|
||||
import { AudioEffect } from "./AudioEffect";
|
||||
import { AudioEffectPool } from "./AudioEffectPool";
|
||||
import { AudioMusic } from "./AudioMusic";
|
||||
import { IAudioData, IAudioParams } from "./IAudio";
|
||||
@@ -35,13 +36,13 @@ export class AudioManager extends Component {
|
||||
* @param url 资源地址
|
||||
* @param params 音效参数
|
||||
*/
|
||||
playEffect(url: string | AudioClip, params?: IAudioParams): Promise<number> {
|
||||
playEffect(url: string | AudioClip, params?: IAudioParams): Promise<AudioEffect> {
|
||||
return this.effect.loadAndPlay(url, params);
|
||||
}
|
||||
|
||||
/** 回收音效播放器 */
|
||||
putEffect(aeid: number, url: string | AudioClip, bundleName?: string) {
|
||||
this.effect.put(aeid, url, bundleName);
|
||||
putEffect(ae: AudioEffect) {
|
||||
this.effect.put(ae);
|
||||
}
|
||||
|
||||
/** 恢复当前暂停的音乐与音效播放 */
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
import { Asset, Button, Component, EventHandler, EventKeyboard, EventTouch, Input, Node, Prefab, Sprite, SpriteFrame, __private, _decorator, input, isValid } from "cc";
|
||||
import { oops } from "../../core/Oops";
|
||||
import { AudioEffect } from "../../core/common/audio/AudioEffect";
|
||||
import { IAudioParams } from "../../core/common/audio/IAudio";
|
||||
import { EventDispatcher } from "../../core/common/event/EventDispatcher";
|
||||
import { EventMessage, ListenerFunc } from "../../core/common/event/EventMessage";
|
||||
@@ -17,8 +18,7 @@ const { ccclass } = _decorator;
|
||||
/** 加载资源类型 */
|
||||
enum ResType {
|
||||
Load,
|
||||
LoadDir,
|
||||
Audio
|
||||
LoadDir
|
||||
}
|
||||
|
||||
/** 资源加载记录 */
|
||||
@@ -33,7 +33,6 @@ interface ResRecord {
|
||||
resId?: number
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 游戏显示对象组件模板
|
||||
* 1、当前对象加载的资源,会在对象释放时,自动释放引用的资源
|
||||
@@ -138,7 +137,7 @@ export class GameComponent extends Component {
|
||||
* @param bundleName 资源包名
|
||||
* @param paths 资源路径
|
||||
*/
|
||||
private addPathToRecord<T>(type: ResType, bundleName: string, paths?: string | string[] | AssetType<T> | ProgressCallback | CompleteCallback | null, resId?: number) {
|
||||
private addPathToRecord<T>(type: ResType, bundleName: string, paths?: string | string[] | AssetType<T> | ProgressCallback | CompleteCallback | null) {
|
||||
if (this.resPaths == null) this.resPaths = new Map();
|
||||
|
||||
var rps = this.resPaths.get(type);
|
||||
@@ -151,45 +150,44 @@ export class GameComponent extends Component {
|
||||
let realBundle = bundleName;
|
||||
for (let index = 0; index < paths.length; index++) {
|
||||
let realPath = paths[index];
|
||||
let key = this.getResKey(realBundle, realPath, resId);
|
||||
let key = this.getResKey(realBundle, realPath);
|
||||
let rp = rps.get(key);
|
||||
if (rp) {
|
||||
rp.refCount++;
|
||||
}
|
||||
else {
|
||||
rps.set(key, { path: realPath, bundle: realBundle, refCount: 1, resId: resId });
|
||||
rps.set(key, { path: realPath, bundle: realBundle, refCount: 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (typeof paths === "string") {
|
||||
let realBundle = bundleName;
|
||||
let realPath = paths;
|
||||
let key = this.getResKey(realBundle, realPath, resId);
|
||||
let key = this.getResKey(realBundle, realPath);
|
||||
let rp = rps.get(key);
|
||||
if (rp) {
|
||||
rp.refCount++;
|
||||
}
|
||||
else {
|
||||
rps.set(key, { path: realPath, bundle: realBundle, refCount: 1, resId: resId });
|
||||
rps.set(key, { path: realPath, bundle: realBundle, refCount: 1 });
|
||||
}
|
||||
}
|
||||
else {
|
||||
let realBundle = oops.res.defaultBundleName;
|
||||
let realPath = bundleName;
|
||||
let key = this.getResKey(realBundle, realPath, resId);
|
||||
let key = this.getResKey(realBundle, realPath);
|
||||
let rp = rps.get(key);
|
||||
if (rp) {
|
||||
rp.refCount++;
|
||||
}
|
||||
else {
|
||||
rps.set(key, { path: realPath, bundle: realBundle, refCount: 1, resId: resId });
|
||||
rps.set(key, { path: realPath, bundle: realBundle, refCount: 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private getResKey(realBundle: string, realPath: string, resId?: number): string {
|
||||
private getResKey(realBundle: string, realPath: string): string {
|
||||
let key = `${realBundle}:${realPath}`;
|
||||
if (resId != null) key += ":" + resId;
|
||||
return key;
|
||||
}
|
||||
|
||||
@@ -304,13 +302,12 @@ export class GameComponent extends Component {
|
||||
|
||||
/** 释放音效资源 */
|
||||
releaseAudioEffect() {
|
||||
if (this.resPaths) {
|
||||
const rps = this.resPaths.get(ResType.Audio);
|
||||
if (rps) {
|
||||
rps.forEach((value: ResRecord) => {
|
||||
oops.audio.putEffect(value.resId!, value.path, value.bundle); // 回收音乐效到音效池中等下次使用
|
||||
});
|
||||
}
|
||||
if (this.audioEffects) {
|
||||
this.audioEffects.forEach((ae: AudioEffect) => {
|
||||
ae.stop();
|
||||
oops.audio.effect.releaseAudioClip(ae);
|
||||
});
|
||||
this.audioEffects.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,37 +343,30 @@ export class GameComponent extends Component {
|
||||
oops.audio.music.loadAndPlay(url, params);
|
||||
}
|
||||
|
||||
/** 音效缓存 */
|
||||
private audioEffects: Map<string, AudioEffect> = null!;
|
||||
|
||||
/**
|
||||
* 播放音效
|
||||
* @param url 资源地址
|
||||
* @param params 音效播放参数
|
||||
*/
|
||||
async playEffect(url: string, params?: IAudioParams): Promise<number> {
|
||||
async playEffect(url: string, params?: IAudioParams): Promise<AudioEffect> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let bundleName = resLoader.defaultBundleName;
|
||||
if (params == null) {
|
||||
params = { bundle: bundleName }
|
||||
}
|
||||
else if (params.bundle != null) {
|
||||
bundleName = params.bundle;
|
||||
}
|
||||
|
||||
// 音效播放完,关闭正在播放状态的音乐效果
|
||||
params.onPlayComplete = (aeid: number, url: string, bundleName: string) => {
|
||||
if (params == null) params = {};
|
||||
params.onPlayComplete = (ae: AudioEffect) => {
|
||||
// 音效播放完前,界面被释放
|
||||
if (!this.isValid) return;
|
||||
|
||||
// 删除界面音效的播放记录
|
||||
const rps = this.resPaths.get(ResType.Audio);
|
||||
if (rps) {
|
||||
const key = this.getResKey(bundleName, url, aeid);
|
||||
rps.delete(key);
|
||||
}
|
||||
this.audioEffects.delete(ae.key);
|
||||
}
|
||||
|
||||
let resId = await oops.audio.playEffect(url, params);
|
||||
this.addPathToRecord(ResType.Audio, bundleName, url, resId); // 支持界面释放时,立即停止所有音效的播放
|
||||
resolve(resId);
|
||||
let ae = await oops.audio.playEffect(url, params);
|
||||
if (this.audioEffects == null) this.audioEffects = new Map();
|
||||
this.audioEffects.set(ae.key, ae);
|
||||
resolve(ae);
|
||||
});
|
||||
}
|
||||
//#endregion
|
||||
@@ -528,11 +518,12 @@ export class GameComponent extends Component {
|
||||
|
||||
// 自动释放资源
|
||||
if (this.resPaths) {
|
||||
this.releaseAudioEffect();
|
||||
this.release();
|
||||
this.releaseDir();
|
||||
this.resPaths.clear();
|
||||
this.resPaths = null!;
|
||||
}
|
||||
|
||||
this.releaseAudioEffect();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user