2025-11-24 12:08:57 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using Framework;
|
|
|
|
|
|
using PhxhSDK;
|
2025-11-27 15:03:25 +08:00
|
|
|
|
using UnityEngine;
|
2025-11-24 12:08:57 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 音频停止池 - 使用 LRU 算法管理停止的 AudioPlayer
|
|
|
|
|
|
/// - 按 key 索引,提高复用率
|
|
|
|
|
|
/// - 分类型限制,防止内存泄漏
|
|
|
|
|
|
/// - LRU 淘汰,自动清理长期不用的 AudioPlayer
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class AudioStoppedPool
|
|
|
|
|
|
{
|
|
|
|
|
|
#region Fields
|
|
|
|
|
|
|
|
|
|
|
|
// 按 key 索引(用于快速查找匹配的 AudioPlayer)
|
|
|
|
|
|
// key 格式: "音频类型_配置key",如 "Music_bgm_01"
|
|
|
|
|
|
private Dictionary<string, LinkedList<AudioPlayer>> _poolByKey;
|
|
|
|
|
|
|
|
|
|
|
|
// 按 ID 索引(用于快速查找和移除)
|
|
|
|
|
|
private Dictionary<int, AudioPlayer> _poolById;
|
|
|
|
|
|
|
|
|
|
|
|
// 当前各类型的数量
|
|
|
|
|
|
private Dictionary<EAudioType, int> _currentCount;
|
|
|
|
|
|
|
|
|
|
|
|
// 各类型的上限
|
|
|
|
|
|
private Dictionary<EAudioType, int> _maxLimit;
|
|
|
|
|
|
|
2025-11-27 15:03:25 +08:00
|
|
|
|
// 记录每个 AudioPlayer 进入停止池的时间戳(毫秒)
|
|
|
|
|
|
private Dictionary<int, long> _stoppedTimeById;
|
|
|
|
|
|
|
|
|
|
|
|
// 各类型的超时时间(秒)- 长时间未使用则释放
|
|
|
|
|
|
private Dictionary<EAudioType, float> _timeoutByType;
|
|
|
|
|
|
|
|
|
|
|
|
// 超时检查定时器(降低检查频率)
|
|
|
|
|
|
private float _checkTimer;
|
|
|
|
|
|
|
|
|
|
|
|
// 临时列表(复用,避免频繁分配)
|
|
|
|
|
|
private readonly List<int> _tempKeysToRemove;
|
|
|
|
|
|
|
2025-11-24 12:08:57 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Init
|
|
|
|
|
|
|
|
|
|
|
|
public AudioStoppedPool()
|
|
|
|
|
|
{
|
|
|
|
|
|
_poolByKey = new Dictionary<string, LinkedList<AudioPlayer>>();
|
|
|
|
|
|
_poolById = new Dictionary<int, AudioPlayer>();
|
|
|
|
|
|
|
|
|
|
|
|
_currentCount = new Dictionary<EAudioType, int>
|
|
|
|
|
|
{
|
|
|
|
|
|
{ EAudioType.Music, 0 },
|
|
|
|
|
|
{ EAudioType.Sound, 0 },
|
|
|
|
|
|
{ EAudioType.Speak, 0 }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
_maxLimit = new Dictionary<EAudioType, int>
|
|
|
|
|
|
{
|
|
|
|
|
|
{ EAudioType.Music, 5 }, // Music 停止池上限 5
|
|
|
|
|
|
{ EAudioType.Sound, 50 }, // Sound 停止池上限 50
|
|
|
|
|
|
{ EAudioType.Speak, 3 } // Speak 停止池上限 3
|
|
|
|
|
|
};
|
2025-11-27 15:03:25 +08:00
|
|
|
|
|
|
|
|
|
|
_stoppedTimeById = new Dictionary<int, long>();
|
|
|
|
|
|
|
|
|
|
|
|
_timeoutByType = new Dictionary<EAudioType, float>
|
|
|
|
|
|
{
|
|
|
|
|
|
{ EAudioType.Music, AudioConstant.MusicStoppedTimeout }, // 60 秒
|
|
|
|
|
|
{ EAudioType.Sound, AudioConstant.SoundStoppedTimeout }, // 30 秒
|
|
|
|
|
|
{ EAudioType.Speak, AudioConstant.SpeakStoppedTimeout } // 20 秒
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
_checkTimer = 0f;
|
|
|
|
|
|
_tempKeysToRemove = new List<int>();
|
2025-11-24 12:08:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Public Methods
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 设置停止池上限
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void SetLimit(EAudioType type, int limit)
|
|
|
|
|
|
{
|
|
|
|
|
|
_maxLimit[type] = limit;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-27 15:03:25 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 设置停止池超时时间(秒)
|
|
|
|
|
|
/// <para>长时间未使用的音频会在超时后自动释放</para>
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="type">音频类型</param>
|
|
|
|
|
|
/// <param name="timeout">超时时间(秒)</param>
|
|
|
|
|
|
public void SetTimeout(EAudioType type, float timeout)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (timeout < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning($"[AudioStoppedPool] Invalid timeout {timeout} for {type}, using 0");
|
|
|
|
|
|
timeout = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
_timeoutByType[type] = timeout;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-24 12:08:57 +08:00
|
|
|
|
/// <summary>
|
2025-11-26 15:43:40 +08:00
|
|
|
|
/// 添加 AudioPlayer 到停止池(带 LRU 淘汰)
|
|
|
|
|
|
/// <para>如果超过该类型的上限,自动淘汰最久未使用的 AudioPlayer</para>
|
2025-11-24 12:08:57 +08:00
|
|
|
|
/// </summary>
|
2025-11-26 15:43:40 +08:00
|
|
|
|
/// <param name="type">音频类型</param>
|
|
|
|
|
|
/// <param name="key">音频配置 key</param>
|
|
|
|
|
|
/// <param name="audio">要添加的 AudioPlayer</param>
|
|
|
|
|
|
/// <returns>被淘汰的 AudioPlayer 列表(需要调用方 Dispose)</returns>
|
2025-11-24 12:08:57 +08:00
|
|
|
|
public List<AudioPlayer> AddStopped(EAudioType type, string key, AudioPlayer audio)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (audio == null || string.IsNullOrEmpty(key))
|
|
|
|
|
|
return new List<AudioPlayer>();
|
|
|
|
|
|
|
|
|
|
|
|
var poolKey = MakePoolKey(type, key);
|
|
|
|
|
|
|
2025-11-27 11:02:18 +08:00
|
|
|
|
// 禁用 GameObject(对象池优化)
|
|
|
|
|
|
audio.SetActive(false);
|
|
|
|
|
|
|
2025-11-24 12:08:57 +08:00
|
|
|
|
// 1. 添加到 key 索引
|
|
|
|
|
|
if (!_poolByKey.TryGetValue(poolKey, out var list))
|
|
|
|
|
|
{
|
|
|
|
|
|
list = new LinkedList<AudioPlayer>();
|
|
|
|
|
|
_poolByKey[poolKey] = list;
|
|
|
|
|
|
}
|
|
|
|
|
|
list.AddFirst(audio); // 添加到链表头部(最近使用)
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 添加到 ID 索引
|
|
|
|
|
|
_poolById[audio.AudioId] = audio;
|
|
|
|
|
|
_currentCount[type]++;
|
|
|
|
|
|
|
2025-11-27 15:03:25 +08:00
|
|
|
|
// 记录进入停止池的时间戳(毫秒)
|
|
|
|
|
|
_stoppedTimeById[audio.AudioId] = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
|
|
|
|
|
|
2025-11-24 12:08:57 +08:00
|
|
|
|
// 3. 检查是否超过上限,执行 LRU 淘汰
|
|
|
|
|
|
var toDestroy = new List<AudioPlayer>();
|
|
|
|
|
|
if (_currentCount[type] > _maxLimit[type])
|
|
|
|
|
|
{
|
|
|
|
|
|
int excessCount = _currentCount[type] - _maxLimit[type];
|
|
|
|
|
|
toDestroy = EvictOldest(type, excessCount);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return toDestroy;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-11-26 15:43:40 +08:00
|
|
|
|
/// 尝试从停止池获取缓存的 AudioPlayer(精确匹配)
|
|
|
|
|
|
/// <para>只返回完全匹配的 audio(同类型 + 同 key),找不到返回 null</para>
|
|
|
|
|
|
/// <para>设计原则:停止池只用于精确复用,不跨 key 复用</para>
|
2025-11-24 12:08:57 +08:00
|
|
|
|
/// </summary>
|
2025-11-26 15:43:40 +08:00
|
|
|
|
/// <param name="type">音频类型</param>
|
|
|
|
|
|
/// <param name="key">音频配置 key</param>
|
|
|
|
|
|
/// <returns>找到返回缓存的 AudioPlayer,否则返回 null</returns>
|
|
|
|
|
|
public AudioPlayer TryGetCached(EAudioType type, string key)
|
2025-11-24 12:08:57 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (string.IsNullOrEmpty(key))
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
|
|
var poolKey = MakePoolKey(type, key);
|
|
|
|
|
|
|
2025-11-26 15:43:40 +08:00
|
|
|
|
// 只返回精确匹配的 audio(同类型 + 同 key)
|
2025-11-24 12:08:57 +08:00
|
|
|
|
if (_poolByKey.TryGetValue(poolKey, out var list) && list.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
var audio = list.First.Value;
|
|
|
|
|
|
RemoveFromPool(audio);
|
|
|
|
|
|
return audio;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-26 15:43:40 +08:00
|
|
|
|
// 找不到精确匹配,返回 null
|
|
|
|
|
|
// 让 AudioManager 决定是创建新的(播放池未满)还是复用最旧的(播放池已满)
|
2025-11-24 12:08:57 +08:00
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 通过 ID 查询停止池中的 AudioPlayer
|
|
|
|
|
|
/// </summary>
|
2025-11-26 15:43:40 +08:00
|
|
|
|
/// <param name="id">AudioPlayer ID</param>
|
|
|
|
|
|
/// <returns>找到返回 AudioPlayer,否则返回 null</returns>
|
2025-11-24 12:08:57 +08:00
|
|
|
|
public AudioPlayer GetById(int id)
|
|
|
|
|
|
{
|
|
|
|
|
|
return _poolById.TryGetValue(id, out var audio) ? audio : null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-11-26 15:43:40 +08:00
|
|
|
|
/// 通过 ID 从停止池移除 AudioPlayer
|
2025-11-24 12:08:57 +08:00
|
|
|
|
/// </summary>
|
2025-11-26 15:43:40 +08:00
|
|
|
|
/// <param name="id">AudioPlayer ID</param>
|
|
|
|
|
|
/// <returns>找到并移除返回 AudioPlayer,否则返回 null</returns>
|
2025-11-24 12:08:57 +08:00
|
|
|
|
public AudioPlayer RemoveById(int id)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_poolById.TryGetValue(id, out var audio))
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
|
|
RemoveFromPool(audio);
|
|
|
|
|
|
return audio;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-11-26 15:43:40 +08:00
|
|
|
|
/// 获取当前各类型的统计信息
|
2025-11-24 12:08:57 +08:00
|
|
|
|
/// </summary>
|
2025-11-26 15:43:40 +08:00
|
|
|
|
/// <returns>(Music数量, Sound数量, Speak数量)</returns>
|
2025-11-24 12:08:57 +08:00
|
|
|
|
public (int music, int sound, int speak) GetStats()
|
|
|
|
|
|
{
|
|
|
|
|
|
return (_currentCount[EAudioType.Music],
|
|
|
|
|
|
_currentCount[EAudioType.Sound],
|
|
|
|
|
|
_currentCount[EAudioType.Speak]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-27 15:03:25 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 更新停止池(检查并释放超时的音频)
|
|
|
|
|
|
/// <para>降低检查频率,避免每帧都检查</para>
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="dt">帧时间(秒)</param>
|
|
|
|
|
|
/// <returns>被释放的 AudioPlayer 列表(需要调用方 Dispose),如果没有则返回 null</returns>
|
|
|
|
|
|
public List<AudioPlayer> Update(float dt)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 降低检查频率(每秒检查一次)
|
|
|
|
|
|
_checkTimer += dt;
|
|
|
|
|
|
if (_checkTimer < AudioConstant.StoppedPoolCheckInterval)
|
|
|
|
|
|
return null; // 返回 null,避免分配空列表
|
|
|
|
|
|
|
|
|
|
|
|
_checkTimer = 0f;
|
|
|
|
|
|
|
|
|
|
|
|
var toDispose = new List<AudioPlayer>();
|
|
|
|
|
|
var currentTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
|
|
|
|
|
|
|
|
|
|
|
// 复用临时列表
|
|
|
|
|
|
_tempKeysToRemove.Clear();
|
|
|
|
|
|
|
|
|
|
|
|
// 直接遍历字典,收集要删除的 key(避免 ToList 的内存分配)
|
|
|
|
|
|
foreach (var kvp in _stoppedTimeById)
|
|
|
|
|
|
{
|
|
|
|
|
|
var audioId = kvp.Key;
|
|
|
|
|
|
var stoppedTime = kvp.Value;
|
|
|
|
|
|
|
|
|
|
|
|
// 获取音频(可能已被移除)
|
|
|
|
|
|
if (!_poolById.TryGetValue(audioId, out var audio))
|
|
|
|
|
|
{
|
|
|
|
|
|
// 收集无效的时间戳,稍后批量删除
|
|
|
|
|
|
_tempKeysToRemove.Add(audioId);
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var type = audio.AudioType;
|
|
|
|
|
|
var timeoutMs = (long)(_timeoutByType[type] * 1000);
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否超时(超时时间 > 0 才启用)
|
|
|
|
|
|
if (timeoutMs > 0 && currentTime - stoppedTime >= timeoutMs)
|
|
|
|
|
|
{
|
|
|
|
|
|
_tempKeysToRemove.Add(audioId);
|
|
|
|
|
|
toDispose.Add(audio);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 批量删除无效的时间戳
|
|
|
|
|
|
foreach (var key in _tempKeysToRemove)
|
|
|
|
|
|
{
|
|
|
|
|
|
_stoppedTimeById.Remove(key);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (toDispose.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
int a = 1;
|
|
|
|
|
|
foreach (var toRemove in toDispose)
|
|
|
|
|
|
{
|
|
|
|
|
|
RemoveFromPool(toRemove);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// 返回结果(空列表返回 null,避免分配)
|
|
|
|
|
|
return toDispose.Count > 0 ? toDispose : null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-24 12:08:57 +08:00
|
|
|
|
/// <summary>
|
2025-11-26 15:43:40 +08:00
|
|
|
|
/// 清空停止池(不释放 AudioPlayer 资源)
|
2025-11-24 12:08:57 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void Clear()
|
|
|
|
|
|
{
|
|
|
|
|
|
_poolByKey.Clear();
|
|
|
|
|
|
_poolById.Clear();
|
2025-11-27 15:03:25 +08:00
|
|
|
|
_stoppedTimeById.Clear();
|
2025-11-26 15:43:40 +08:00
|
|
|
|
ResetCounts();
|
2025-11-24 12:08:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 释放所有 AudioPlayer 资源并清空停止池
|
|
|
|
|
|
/// <para>适用于场景卸载、关卡退出等需要彻底清理的场景</para>
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>释放的 AudioPlayer 数量</returns>
|
|
|
|
|
|
public int DisposeAll()
|
|
|
|
|
|
{
|
|
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
2025-11-26 15:43:40 +08:00
|
|
|
|
// 释放所有 AudioPlayer 资源
|
2025-11-24 12:08:57 +08:00
|
|
|
|
foreach (var list in _poolByKey.Values)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var audio in list)
|
|
|
|
|
|
{
|
|
|
|
|
|
audio.Dispose();
|
|
|
|
|
|
count++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 清空池子
|
|
|
|
|
|
_poolByKey.Clear();
|
|
|
|
|
|
_poolById.Clear();
|
2025-11-27 15:03:25 +08:00
|
|
|
|
_stoppedTimeById.Clear();
|
2025-11-26 15:43:40 +08:00
|
|
|
|
ResetCounts();
|
2025-11-24 12:08:57 +08:00
|
|
|
|
|
|
|
|
|
|
return count;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Private Methods
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 从停止池移除 AudioPlayer
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void RemoveFromPool(AudioPlayer audio)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (audio == null)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
// 从 ID 索引移除
|
|
|
|
|
|
_poolById.Remove(audio.AudioId);
|
|
|
|
|
|
|
|
|
|
|
|
// 从 key 索引移除
|
|
|
|
|
|
var poolKey = MakePoolKey(audio.AudioType, audio.CurrentPlayingKey);
|
|
|
|
|
|
if (_poolByKey.TryGetValue(poolKey, out var list))
|
|
|
|
|
|
{
|
|
|
|
|
|
list.Remove(audio);
|
|
|
|
|
|
if (list.Count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
_poolByKey.Remove(poolKey);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新计数
|
|
|
|
|
|
_currentCount[audio.AudioType]--;
|
2025-11-27 15:03:25 +08:00
|
|
|
|
|
|
|
|
|
|
// 清除时间戳
|
|
|
|
|
|
_stoppedTimeById.Remove(audio.AudioId);
|
2025-11-24 12:08:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-11-26 15:43:40 +08:00
|
|
|
|
/// LRU 淘汰:移除指定类型中最久未使用的 N 个 AudioPlayer
|
|
|
|
|
|
/// <para>从各个 key 的链表尾部收集(尾部 = 最久未使用)</para>
|
2025-11-24 12:08:57 +08:00
|
|
|
|
/// </summary>
|
2025-11-26 15:43:40 +08:00
|
|
|
|
/// <param name="type">音频类型</param>
|
|
|
|
|
|
/// <param name="count">要淘汰的数量</param>
|
|
|
|
|
|
/// <returns>被淘汰的 AudioPlayer 列表</returns>
|
2025-11-24 12:08:57 +08:00
|
|
|
|
private List<AudioPlayer> EvictOldest(EAudioType type, int count)
|
|
|
|
|
|
{
|
2025-11-26 15:43:40 +08:00
|
|
|
|
var evicted = new List<AudioPlayer>(count);
|
2025-11-24 12:08:57 +08:00
|
|
|
|
var typePrefix = $"{type}_";
|
|
|
|
|
|
|
2025-11-26 15:43:40 +08:00
|
|
|
|
// 从所有匹配类型的 key 中收集最久未使用的 AudioPlayer
|
2025-11-24 12:08:57 +08:00
|
|
|
|
foreach (var kv in _poolByKey)
|
|
|
|
|
|
{
|
2025-11-26 15:43:40 +08:00
|
|
|
|
if (!kv.Key.StartsWith(typePrefix))
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
// 从链表尾部开始收集(尾部 = 最久未使用)
|
|
|
|
|
|
var node = kv.Value.Last;
|
|
|
|
|
|
while (node != null && evicted.Count < count)
|
2025-11-24 12:08:57 +08:00
|
|
|
|
{
|
2025-11-26 15:43:40 +08:00
|
|
|
|
evicted.Add(node.Value);
|
|
|
|
|
|
node = node.Previous;
|
2025-11-24 12:08:57 +08:00
|
|
|
|
}
|
2025-11-26 15:43:40 +08:00
|
|
|
|
|
|
|
|
|
|
// 已收集足够数量,提前退出
|
|
|
|
|
|
if (evicted.Count >= count)
|
|
|
|
|
|
break;
|
2025-11-24 12:08:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-26 15:43:40 +08:00
|
|
|
|
// 从池中移除
|
|
|
|
|
|
foreach (var audio in evicted)
|
2025-11-24 12:08:57 +08:00
|
|
|
|
{
|
|
|
|
|
|
RemoveFromPool(audio);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-26 15:43:40 +08:00
|
|
|
|
return evicted;
|
2025-11-24 12:08:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-11-26 15:43:40 +08:00
|
|
|
|
/// 生成池 key(格式:类型_配置key)
|
2025-11-24 12:08:57 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
private string MakePoolKey(EAudioType type, string key)
|
|
|
|
|
|
{
|
|
|
|
|
|
return $"{type}_{key}";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-26 15:43:40 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 重置所有类型的计数
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void ResetCounts()
|
|
|
|
|
|
{
|
|
|
|
|
|
_currentCount[EAudioType.Music] = 0;
|
|
|
|
|
|
_currentCount[EAudioType.Sound] = 0;
|
|
|
|
|
|
_currentCount[EAudioType.Speak] = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-24 12:08:57 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-27 15:03:25 +08:00
|
|
|
|
|