using UnityEngine; using Lean.Pool; using AK.Wwise; using SLSUtilities.LeanPoolAssistance; // 引用 Wwise namespace SLSUtilities.WwiseAssistance { /// /// 挂载在 AudioPoint 预制体上,负责管理单个音频实例的生命周期 /// public partial class AudioPoint : PooledObject { public uint playingID = AkUnitySoundEngine.AK_INVALID_PLAYING_ID; public uint eventID = uint.MaxValue; /// /// 播放指定 ID 的事件 /// public uint Play(uint eventID) { this.eventID = eventID; // PostEvent 并注册 EndOfEvent 回调 playingID = AkUnitySoundEngine.PostEvent(eventID, gameObject, (uint)AkCallbackType.AK_EndOfEvent, OnEventFinished, null); // 安全检查:如果 ID 无效(比如Bank没加载),立即回收,防止对象泄漏 if (playingID == AkUnitySoundEngine.AK_INVALID_PLAYING_ID) { Debug.LogWarning($"Wwise Event ID [{eventID}] 播放失败,正在回收对象。"); LeanPool.Despawn(gameObject); } return playingID; } /// /// 手动停止播放(支持淡出),用于 Loop 音效 /// /// 淡出时间(毫秒) public void Stop(int fadeOutMs = 0) { if (playingID != AkUnitySoundEngine.AK_INVALID_PLAYING_ID) { // 执行 Stop Action AkUnitySoundEngine.ExecuteActionOnPlayingID(AkActionOnEventType.AkActionOnEventType_Stop, playingID, fadeOutMs, AkCurveInterpolation.AkCurveInterpolation_Sine); // 注意:这里不调用 DespawnSelf。 // Wwise 停止并淡出后,会触发 AK_EndOfEvent,由 OnEventFinished 负责回收。 } else { // 如果没有在播放,直接回收 LeanPool.Despawn(gameObject); } } public void Pause(int fadeOutMs = 0) { if (playingID != AkUnitySoundEngine.AK_INVALID_PLAYING_ID) { AkUnitySoundEngine.ExecuteActionOnPlayingID( AkActionOnEventType.AkActionOnEventType_Pause, playingID, fadeOutMs, AkCurveInterpolation.AkCurveInterpolation_Linear ); } } // 【新增】继续 public void Resume(int fadeInMs = 0) { if (playingID != AkUnitySoundEngine.AK_INVALID_PLAYING_ID) { AkUnitySoundEngine.ExecuteActionOnPlayingID( AkActionOnEventType.AkActionOnEventType_Resume, playingID, fadeInMs, AkCurveInterpolation.AkCurveInterpolation_Linear ); } } } public partial class AudioPoint { /// /// Wwise 内部回调 /// private void OnEventFinished(object in_cookie, AkCallbackType in_type, object in_info) { if (in_type == AkCallbackType.AK_EndOfEvent) { // 确保在 Unity 主线程且对象有效时回收 // (Wwise 回调通常在主线程,但为了防止 Destroy 竞争条件,加个检查) if (this != null && gameObject.activeInHierarchy) { LeanPool.Despawn(gameObject); } } } public override void OnDespawn() { playingID = AkUnitySoundEngine.AK_INVALID_PLAYING_ID; eventID = 0; base.OnDespawn(); } } }