using System; using System.Collections; using System.Collections.Generic; using Cielonos.MainGame; using Lean.Pool; using Sirenix.OdinInspector; using UniRx; using UnityEngine; using Event = AK.Wwise.Event; namespace SLSFramework.WwiseAssistance { public class AudioContainer : SerializedMonoBehaviour { public Dictionary soundEventDictionary = new Dictionary(); private HashSet normalAudioPlayingIDs; private void Awake() { soundEventDictionary ??= new Dictionary(); normalAudioPlayingIDs = new HashSet(); } /// /// 触发自定义的Wwise事件 /// public void PostEvent(string eventName, GameObject attachedObject = null) { Event evt = soundEventDictionary[eventName]; if (evt == null) return; attachedObject = attachedObject == null ? gameObject : attachedObject; evt.Post(attachedObject); } /// /// 依附于GameObject播放3D音频,attachedObject为null时默认为当前GameObject /// public uint PlaySoundFX(string soundName, GameObject attachedObject = null, bool spawnTempObject = false) { if (!soundEventDictionary.TryGetValue(soundName, out Event sound)) { Debug.LogWarning($"Sound event '{soundName}' not found in dictionary."); return 0; } attachedObject = attachedObject == null ? gameObject : attachedObject; uint playingID; // *** 修正 ***: 在这里声明 playingID if (spawnTempObject) { GameObject soundObj = LeanPool.Spawn(MainGameManager.BasePrefabs.audioPoint, attachedObject.transform); // *** 修正 ***: // 1. 将 soundObj 本身作为 cookie 传递。 // 2. 捕获 Post() 返回的 playingID = sound.Post(soundObj, (uint)AkCallbackType.AK_EndOfEvent, AutoDespawnCallback, soundObj); soundObj.name = $"{soundName}-WwiseEvent{playingID}"; // 使用正确的 playingID } else { // *** 修正 ***: // 1. cookie 传递 null,因为我们不需要它。 // 2. 捕获 Post() 返回的 playingID。 playingID = sound.Post(attachedObject,(uint)AkCallbackType.AK_EndOfEvent, OnEventCallback, null); } // *** 修正 ***: // 将捕获到的、正确的 playingID 添加到集合中 // (还应检查 Post 是否成功,不为0) if (playingID != 0) { normalAudioPlayingIDs.Add(playingID); } return playingID; } /// /// 在指定位置播放3D音频 /// public uint PlaySoundFX(string soundName, Vector3 position, bool isLoop = false) { Event sound = soundEventDictionary[soundName]; if (sound == null) return 0; GameObject soundObj = LeanPool.Spawn(MainGameManager.BasePrefabs.audioPoint, position, Quaternion.identity); // *** 修正 ***: // 1. 将 soundObj 作为 cookie 传递。 // 2. 捕获 Post() 返回的 playingID。 uint playingID = sound.Post(soundObj, (uint)AkCallbackType.AK_EndOfEvent, AutoDespawnCallback, soundObj); soundObj.name = $"{soundName}-WwiseEvent{playingID}"; // 使用正确的 playingID if (playingID != 0) { normalAudioPlayingIDs.Add(playingID); } return playingID; } /// /// 停止播放音效 /// public void StopSoundFX(uint playingID) { if (normalAudioPlayingIDs.Contains(playingID)) { AkUnitySoundEngine.StopPlayingID(playingID); } else { Debug.LogWarning($"No sound is playing with PlayingID: {playingID}"); } } /// /// 以淡出效果停止播放音效 /// public void StopSoundWithFadeOut(uint playingID, float fadeOutDuration) { if (normalAudioPlayingIDs.Contains(playingID)) { AkUnitySoundEngine.ExecuteActionOnPlayingID( AkActionOnEventType.AkActionOnEventType_Stop, playingID, (int)(fadeOutDuration * 1000), // 将秒数转为毫秒 AkCurveInterpolation.AkCurveInterpolation_Sine // 选择淡出曲线 ); } else { Debug.LogWarning($"No sound is playing with PlayingID: {playingID}"); } } /// /// 自动回收临时音频对象 /// private void AutoDespawnCallback(object in_cookie, AkCallbackType in_type, AkCallbackInfo in_info) { if (in_type == AkCallbackType.AK_EndOfEvent) { // *** 修正 ***: cookie 现在是 GameObject GameObject soundObj = (GameObject)in_cookie; // *** 修正 ***: 从 AkCallbackInfo (in_info) 中获取 playingID uint playingID = 0; if (in_info is AkEventCallbackInfo eventInfo) { playingID = eventInfo.playingID; } if (playingID != 0 && normalAudioPlayingIDs.Contains(playingID)) { normalAudioPlayingIDs.Remove(playingID); if (soundObj != null) // 最好检查一下对象是否仍然存在 { LeanPool.Despawn(soundObj); } } } } private void OnEventCallback(object in_cookie, AkCallbackType in_type, AkCallbackInfo in_info) { if (in_type == AkCallbackType.AK_EndOfEvent) { // *** 修正 ***: 从 AkCallbackInfo (in_info) 中获取 playingID uint playingID = 0; if (in_info is AkEventCallbackInfo eventInfo) { playingID = eventInfo.playingID; } if (playingID != 0 && normalAudioPlayingIDs.Contains(playingID)) { normalAudioPlayingIDs.Remove(playingID); } } } } }