using System; using UnityEngine; using System.Collections.Generic; using System.Threading; using UnityEngine.SceneManagement; namespace Stary.Evo.AudioCore { /// /// 对象池 /// public interface IAudioSourcePool { /// /// 将对象存进池里 /// /// void Creation(); /// /// 从未激活池里面取对象,并放入激活池 /// /// AudioSourceToken Spawn(); /// /// 从激活池中释放对象到未激活池中 /// AudioSourceToken RecycleSpawn(AudioSourceToken source); /// /// 回收对象 /// void RecycleAll(); /// /// 清空对象池 /// void RemoveAll(); int GetPolLength(); } public class AudioSourcePool : IAudioSourcePool { private Transform active; /// /// 回收对象的父物体 /// private Transform recycle; protected List activepool = new List(); protected Queue inactivepool = new Queue(); //没有回收的个数 protected int noRecycleCount; /// /// 对象池物体总数量 /// public int poolCount = 0; /// /// 对象池最大数量 /// private int poolSize = 0; public AudioSourcePool(string poolName, int poolSize) { this.poolSize = poolSize; var poolObject = GameObject.Find(poolName); if (poolObject == null) { // 如果不存在,创建一个新对象 active = new GameObject(poolName).transform; } else { active = poolObject.transform; } var recycleObject = GameObject.Find($"recycle_{poolName}"); if (recycle == null) { // 如果不存在,创建一个新对象 recycle = new GameObject($"recycle_{poolName}").transform; } else { recycle = recycleObject.transform; } } /// /// 将对象存进池里 /// /// public void Creation() { AudioSource source = CreatAudioSource(); if (source == null) { Debug.LogErrorFormat("对象池【{0}】已达最大数量【{1}】,无法创建新对象", active.name, poolSize); return; } // if (type == "Music") // { // newObject.GetComponent().loop = true; // } inactivepool.Enqueue(new AudioSourceToken(source, new CancellationTokenSource())); noRecycleCount++; } /// /// 从未激活池里面取对象,并放入激活池 /// /// 如果为空是否new出来 public AudioSourceToken Spawn() { AudioSourceToken audioSourceToken = null; if (noRecycleCount > 0) { audioSourceToken = inactivepool.Dequeue(); audioSourceToken.source.transform.parent = active; noRecycleCount--; if (audioSourceToken.source == null) Debug.LogErrorFormat("对象池中不存在此对象【{0}】请排查代码", audioSourceToken.source); audioSourceToken.cancellationToken = new CancellationTokenSource(); } else { var source = CreatAudioSource(); if (source == null) { Debug.LogErrorFormat("对象池【{0}】已达最大数量【{1}】,无法创建新对象", active.name, poolSize); return null; } audioSourceToken = new AudioSourceToken(source, new CancellationTokenSource()); } audioSourceToken.source.transform.localPosition = Vector3.zero; audioSourceToken.source.transform.localRotation = Quaternion.identity; audioSourceToken.source.transform.localScale = Vector3.one; activepool.Add(audioSourceToken); return audioSourceToken; } /// /// 从激活池中释放对象到未激活池中 /// public AudioSourceToken RecycleSpawn(AudioSourceToken audioSourceToken) { if (audioSourceToken.source != null && activepool.Contains(audioSourceToken)) { activepool.Remove(audioSourceToken); inactivepool.Enqueue(audioSourceToken); audioSourceToken.source.transform.parent = recycle; audioSourceToken.source.Stop(); // 停止播放 audioSourceToken.source.clip = null; // 清空音频剪辑 audioSourceToken.source.volume = 1f; // 音量大小恢复 noRecycleCount++; // 释放CancellationToken资源 audioSourceToken.Dispose(); } return null; } /// /// 回收所有对象 /// public void RecycleAll() { for (int i = 0; i < activepool.Count; i++) { RecycleSpawn(activepool[i]); } } /// /// 清空对象池 /// public void RemoveAll() { noRecycleCount = 0; poolCount = 0; GameObject.Destroy(active.gameObject); inactivepool.Clear(); GameObject.Destroy(recycle.gameObject); for (int i = 0; i < activepool.Count; i++) { RecycleSpawn(activepool[i]); } activepool.Clear(); } /// /// 创建一个新的AudioSource对象 /// /// private AudioSource CreatAudioSource() { if (poolCount >= poolSize && poolSize > 0) return null; poolCount++; AudioSource source = new GameObject($"{active.name}_{poolCount}").AddComponent(); source.gameObject.transform.SetParent(recycle); source.transform.SetParent(active.transform); // 将新对象作为当前对象的子对象 source.playOnAwake = false; // 添加 AudioSource 组件并禁用自动播放 return source; } public int GetPolLength() { return inactivepool.Count; } } public class AudioSourceToken { public AudioSource source; public CancellationTokenSource cancellationToken; public AudioSourceToken(AudioSource source, CancellationTokenSource cancellationToken) { this.source = source; this.cancellationToken = cancellationToken; } public AudioSourceToken(AudioSourceToken sourceToken) { this.source = sourceToken.source; this.cancellationToken = sourceToken.cancellationToken; } // 添加释放方法 public void Dispose() { // 使用局部变量避免多线程环境下的竞态条件 var cts = Interlocked.Exchange(ref cancellationToken, null); if (cts != null) { try { // 取消令牌,触发注册的回调 cts.Cancel(); cts.Dispose(); } catch (ObjectDisposedException) { // 已经被释放,无需处理 } catch (AggregateException ex) { // 处理注册回调抛出的异常 // 只记录第一个异常,避免日志过于冗长 Debug.LogError($"CancellationTokenSource.Cancel() 回调抛出异常: {ex.InnerExceptions[0]}"); // 可以选择不重新抛出,避免中断释放流程 } catch (Exception ex) { Debug.LogError($"CancellationTokenSource.Cancel() 抛出异常: {ex}"); } finally { // 确保始终释放资源 try { cts.Dispose(); } catch (ObjectDisposedException) { // 已经被释放,无需处理 } } } } } }