| | |
| | | // 记录每个音效ID当前播放的AudioSource |
| | | private Dictionary<int, List<AudioSource>> audioIdToSources = new Dictionary<int, List<AudioSource>>(); |
| | | |
| | | // 清理用缓存列表,避免每帧分配 |
| | | private List<int> _keysToRemoveCache = new List<int>(); |
| | | |
| | | // 音频剪辑缓存 |
| | | private Dictionary<int, AudioClip> audioClipCache = new Dictionary<int, AudioClip>(); |
| | | |
| | | // 当前播放速度 |
| | | private float currentSpeedRatio = 1f; |
| | | |
| | | // 跟踪AudioSource总数,避免GetComponents分配 |
| | | private int audioSourceCount = 0; |
| | | |
| | | // 是否有焦点 |
| | | private bool hasFocus = true; |
| | |
| | | source.spatialBlend = 0f; // 2D音效 |
| | | audioSourcePool.Enqueue(source); |
| | | } |
| | | audioSourceCount = INITIAL_AUDIO_POOL; |
| | | Debug.Log($"<color=cyan>BattleSoundManager [{battleField.guid}]: 初始化了 {INITIAL_AUDIO_POOL} 个 AudioSource</color>"); |
| | | } |
| | | |
| | |
| | | // 检查是否有焦点,无焦点时不播放 |
| | | if (!hasFocus) |
| | | { |
| | | #if UNITY_EDITOR |
| | | Debug.Log($"<color=yellow>BattleSoundManager [{battleField.guid}]: 无焦点,拒绝播放音效 {audioId}</color>"); |
| | | #endif |
| | | return; |
| | | } |
| | | |
| | | // 检查该音效是否已达到播放上限 |
| | | if (!CanPlayAudio(audioId)) |
| | | { |
| | | #if UNITY_EDITOR |
| | | Debug.Log($"<color=yellow>BattleSoundManager [{battleField.guid}]: 音效 {audioId} 达到播放上限,拒绝播放</color>"); |
| | | #endif |
| | | return; |
| | | } |
| | | |
| | | var audioClip = await GetAudioClip(audioId); |
| | | if (audioClip == null) |
| | | { |
| | | #if UNITY_EDITOR |
| | | Debug.Log($"<color=red>BattleSoundManager [{battleField.guid}]: 无法加载音效 {audioId}</color>"); |
| | | #endif |
| | | return; |
| | | } |
| | | |
| | |
| | | AudioSource source = GetAvailableAudioSource(); |
| | | if (source == null) |
| | | { |
| | | #if UNITY_EDITOR |
| | | Debug.Log($"<color=red>BattleSoundManager [{battleField.guid}]: 无法获取AudioSource,池数量={audioSourcePool.Count},活跃数量={activeAudioSources.Count}</color>"); |
| | | #endif |
| | | return; |
| | | } |
| | | |
| | |
| | | source.clip = audioClip; |
| | | source.Play(); |
| | | |
| | | #if UNITY_EDITOR |
| | | Debug.Log($"<color=green>BattleSoundManager [{battleField.guid}]: 播放音效 {audioId} - {audioClip.name}</color>"); |
| | | #endif |
| | | |
| | | // 标记为活跃 |
| | | if (!activeAudioSources.Contains(source)) |
| | |
| | | { |
| | | return source; |
| | | } |
| | | #if UNITY_EDITOR |
| | | Debug.Log($"<color=orange>BattleSoundManager [{battleField.guid}]: 池中的AudioSource已被销毁,跳过</color>"); |
| | | #endif |
| | | } |
| | | |
| | | // 计算当前总的 AudioSource 数量 |
| | | int totalAudioSources = audioSourceObject.GetComponents<AudioSource>().Length; |
| | | |
| | | if (totalAudioSources >= MAX_AUDIO_SOURCES) |
| | | if (audioSourceCount >= MAX_AUDIO_SOURCES) |
| | | { |
| | | // 达到上限,不再创建,丢弃这次播放请求 |
| | | #if UNITY_EDITOR |
| | | Debug.Log($"BattleSoundManager: AudioSource 数量已达上限 {MAX_AUDIO_SOURCES},无法播放新音效"); |
| | | #endif |
| | | return null; |
| | | } |
| | | |
| | |
| | | newSource.playOnAwake = false; |
| | | newSource.loop = false; |
| | | newSource.spatialBlend = 0f; // 2D音效 |
| | | audioSourceCount++; |
| | | |
| | | Debug.Log($"<color=cyan>BattleSoundManager [{battleField.guid}]: 动态创建新AudioSource,当前总数={totalAudioSources + 1}</color>"); |
| | | #if UNITY_EDITOR |
| | | Debug.Log($"<color=cyan>BattleSoundManager [{battleField.guid}]: 动态创建新AudioSource,当前总数={audioSourceCount}</color>"); |
| | | #endif |
| | | |
| | | return newSource; |
| | | } |
| | |
| | | } |
| | | |
| | | // 清理 audioIdToSources 中已停止播放的 AudioSource |
| | | var keysToRemove = new List<int>(); |
| | | _keysToRemoveCache.Clear(); |
| | | foreach (var kvp in audioIdToSources) |
| | | { |
| | | kvp.Value.RemoveAll(s => s == null || !s.isPlaying); |
| | | if (kvp.Value.Count == 0) |
| | | { |
| | | keysToRemove.Add(kvp.Key); |
| | | _keysToRemoveCache.Add(kvp.Key); |
| | | } |
| | | } |
| | | |
| | | // 移除空的音效ID记录 |
| | | foreach (var key in keysToRemove) |
| | | foreach (var key in _keysToRemoveCache) |
| | | { |
| | | audioIdToSources.Remove(key); |
| | | } |
| | |
| | | int activeCount = activeAudioSources.Count; |
| | | int totalStopped = 0; |
| | | |
| | | AudioSource[] allSources = null; |
| | | |
| | | // 不依赖列表,直接停止 GameObject 上的所有 AudioSource |
| | | if (audioSourceObject != null) |
| | | { |
| | | var allSources = audioSourceObject.GetComponents<AudioSource>(); |
| | | allSources = audioSourceObject.GetComponents<AudioSource>(); |
| | | #if UNITY_EDITOR |
| | | Debug.Log($"<color=red>BattleSoundManager [{battleField.guid}]: StopAllSounds - GameObject上共有 {allSources.Length} 个AudioSource</color>"); |
| | | #endif |
| | | |
| | | foreach (var source in allSources) |
| | | { |
| | |
| | | { |
| | | if (source.isPlaying) |
| | | { |
| | | #if UNITY_EDITOR |
| | | Debug.Log($"<color=red> 停止正在播放的: {source.clip?.name}</color>"); |
| | | #endif |
| | | totalStopped++; |
| | | } |
| | | source.Stop(); |
| | |
| | | } |
| | | } |
| | | |
| | | #if UNITY_EDITOR |
| | | Debug.Log($"<color=red>BattleSoundManager [{battleField.guid}]: StopAllSounds - 活跃列表={activeCount}, 实际停止={totalStopped}</color>"); |
| | | #endif |
| | | |
| | | // 清空所有列表 |
| | | activeAudioSources.Clear(); |
| | | audioIdToSources.Clear(); |
| | | |
| | | // 重建对象池 |
| | | // 重建对象池(复用上面已获取的数组) |
| | | audioSourcePool.Clear(); |
| | | if (audioSourceObject != null) |
| | | if (allSources != null) |
| | | { |
| | | var allSources = audioSourceObject.GetComponents<AudioSource>(); |
| | | foreach (var source in allSources) |
| | | { |
| | | if (source != null) |
| | |
| | | } |
| | | } |
| | | |
| | | #if UNITY_EDITOR |
| | | Debug.Log($"<color=red>BattleSoundManager [{battleField.guid}]: StopAllSounds 完成</color>"); |
| | | #endif |
| | | } |
| | | |
| | | /// <summary> |