using System.Collections.Generic; using UnityEngine; using AK.Wwise; using Lean.Pool; using Sirenix.OdinInspector; using SLSUtilities.General; namespace SLSUtilities.WwiseAssistance { public partial class AudioManager : Singleton { [Title("Settings")] [Required] public GameObject audioPoint; public List soundBanks; [Title("Subsystems")] public BackgroundMusicManager backgroundMusicManager; private static Dictionary _trackedPlayingIDs = new Dictionary(); protected override void Awake() { base.Awake(); soundBanks.ForEach(bank => bank.Load()); } } public partial class AudioManager { /// /// 【核心方法】在指定位置播放 3D 音效 /// 使用方法: AudioManager.Instance.PlayEvent(AK.EVENTS.EXPLOSION, position); /// /// AK.EVENTS 中的静态 ID /// 世界坐标 /// 返回 WwiseEmitter,以便需要时手动 Stop public static AudioPoint Post(uint eventID, Vector3 position = default) { if (eventID == 0) return null; AudioPoint point = LeanPool.Spawn(instance.audioPoint, position, Quaternion.identity).GetComponent(); point.Play(eventID); return point; } public static uint Post(uint eventID, GameObject attachedObject) { if (eventID == 0 || attachedObject == null) return AkUnitySoundEngine.AK_INVALID_PLAYING_ID; return AkUnitySoundEngine.PostEvent(eventID, attachedObject); } public static AudioPoint Post(string eventName, Vector3 position) { return Post(AkUnitySoundEngine.GetIDFromString(eventName), position); } public static void Post(string eventName, GameObject attachedObject) { Post(AkUnitySoundEngine.GetIDFromString(eventName), attachedObject); } public static void Stop(uint playingID, int fadeOutMs = 0) { if (playingID == AkUnitySoundEngine.AK_INVALID_PLAYING_ID) return; AkUnitySoundEngine.ExecuteActionOnPlayingID( AkActionOnEventType.AkActionOnEventType_Stop, playingID, fadeOutMs, AkCurveInterpolation.AkCurveInterpolation_Linear ); } public void StopAll() { AkUnitySoundEngine.StopAll(); _trackedPlayingIDs.Clear(); } } public partial class AudioManager { private static void RegisterTracking(string trackingKey, uint playingID) { if (playingID != AkUnitySoundEngine.AK_INVALID_PLAYING_ID) { _trackedPlayingIDs[trackingKey] = playingID; } } public static void Post(string trackingKey, uint eventID, Vector3 position = default) { Stop(trackingKey); AudioPoint point = Post(eventID, position); uint playingID = point.eventID; RegisterTracking(trackingKey, playingID); } public static void Post(string trackingKey, string eventName, Vector3 position = default) { Post(trackingKey, AkUnitySoundEngine.GetIDFromString(eventName), position); } public static void Post(string trackingKey, uint eventID, GameObject attachedObject) { Stop(trackingKey); uint playingID = Post(eventID, attachedObject); RegisterTracking(trackingKey, playingID); } public static void Post(string trackingKey, string eventName, GameObject attachedObject) { Post(trackingKey, AkUnitySoundEngine.GetIDFromString(eventName), attachedObject); } public static void Pause(string trackingKey, int fadeOutMs = 0) { if (_trackedPlayingIDs.TryGetValue(trackingKey, out uint playingID)) { AkUnitySoundEngine.ExecuteActionOnPlayingID( AkActionOnEventType.AkActionOnEventType_Pause, playingID, fadeOutMs, AkCurveInterpolation.AkCurveInterpolation_Linear ); } } public static void PauseAllTrackedEvents(int fadeOutMs = 0) { foreach (var playingID in _trackedPlayingIDs.Values) { AkUnitySoundEngine.ExecuteActionOnPlayingID( AkActionOnEventType.AkActionOnEventType_Pause, playingID, fadeOutMs, AkCurveInterpolation.AkCurveInterpolation_Linear ); } } // --- 【新增】核心控制:继续 --- public static void Resume(string trackingKey, int fadeInMs = 0) { if (_trackedPlayingIDs.TryGetValue(trackingKey, out uint playingID)) { AkUnitySoundEngine.ExecuteActionOnPlayingID( AkActionOnEventType.AkActionOnEventType_Resume, playingID, fadeInMs, AkCurveInterpolation.AkCurveInterpolation_Linear ); } } public static void ResumeAllTrackedEvents(int fadeInMs = 0) { foreach (var playingID in _trackedPlayingIDs.Values) { AkUnitySoundEngine.ExecuteActionOnPlayingID( AkActionOnEventType.AkActionOnEventType_Resume, playingID, fadeInMs, AkCurveInterpolation.AkCurveInterpolation_Linear ); } } /// /// 【新增】通过 Key 停止特定音效 /// public static void Stop(string trackingKey, int fadeOutMs = 0) { if (_trackedPlayingIDs.TryGetValue(trackingKey, out uint playingID)) { Stop(playingID, fadeOutMs); _trackedPlayingIDs.Remove(trackingKey); } } /// /// 【新增】停止所有被追踪的循环音效 (常用于切换场景前) /// public static void StopAllTrackedEvents(int fadeOutMs = 0) { foreach (var playingID in _trackedPlayingIDs.Values) { Stop(playingID, fadeOutMs); } _trackedPlayingIDs.Clear(); } } public partial class AudioManager { /// /// 设置全局参数 (RTPC) /// 例如: "MasterVolume", "MusicVolume", "PlayerHealth" /// public void SetRTPC(string rtpcName, float value) { AkUnitySoundEngine.SetRTPCValue(rtpcName, value); } /// /// 设置状态 (State) /// 例如: Group="MusicState", State="Combat" / "Explore" /// public void SetState(string stateGroup, string stateName) { AkUnitySoundEngine.SetState(stateGroup, stateName); } /// /// 设置全局开关 (Switch) - 通常用于特定的全局对象 /// public void SetGlobalSwitch(string switchGroup, string switchName) { // 对于全局Switch,通常传一个全局GameObject,或者使用 Wwise 的 Global Scope AkUnitySoundEngine.SetSwitch(switchGroup, switchName, gameObject); } } }