using System; using System.Collections; using System.Collections.Generic; using Lean.Pool; using Sirenix.OdinInspector; using UnityEngine; using AK.Wwise; using Event = AK.Wwise.Event; namespace Ichni { public class AudioContainer : SerializedMonoBehaviour { public Dictionary SoundEventDictionary; public Dictionary SoundRTPCDictionary; private Dictionary normalAudioPlayingIDs; private void Awake() { normalAudioPlayingIDs = new Dictionary(); SoundEventDictionary ??= new Dictionary(); SoundRTPCDictionary ??= new Dictionary(); } public void PostEvent(string eventName, GameObject attachedObject = null) { Event evt = SoundEventDictionary[eventName]; attachedObject = attachedObject == null ? gameObject : attachedObject; evt.Post(attachedObject); } public void StopEvent(string eventName) { if (SoundEventDictionary.TryGetValue(eventName, out Event soundEvent)) { soundEvent.Stop(gameObject); } else { Debug.LogWarning($"Sound event '{eventName}' not found in SoundEventDictionary."); } } public void SetSwitch(Switch targetSwitch) { targetSwitch?.SetValue(gameObject); } public void SetRTPC(string rtpcName, float value) { if (SoundRTPCDictionary.TryGetValue(rtpcName, out RTPC rtpc)) { AkSoundEngine.SetRTPCValue(rtpc.Id, value, gameObject); } else { Debug.LogWarning($"RTPC '{rtpcName}' not found in SoundRTPCDictionary."); } } /// /// 依附于GameObject播放音频,attachedObject为null时默认为当前GameObject。 /// 在Wwise中设置音频的空间属性(2D或3D)。 /// public void PlaySoundFX(string soundName, GameObject attachedObject = null, bool spawnTempObject = false) { var sound = SoundEventDictionary[soundName]; attachedObject = attachedObject == null ? gameObject : attachedObject; if (spawnTempObject) { GameObject soundObj = LeanPool.Spawn(GameManager.instance.basePrefabs.audioEventObject, attachedObject.transform); soundObj.name = String.Format("{0}-WwiseEvent", soundName); sound.Post(soundObj, (uint)AkCallbackType.AK_EndOfEvent, AutoDespawnCallback, soundObj); } else { sound.Post(attachedObject,(uint)AkCallbackType.AK_EndOfEvent, OnEventCallback, soundName); } normalAudioPlayingIDs[soundName] = sound.PlayingId; } /// /// 在指定位置播放音频 /// 在Wwise中设置音频的空间属性(2D或3D)。 /// public void PlaySoundFX(string soundName, Vector3 position, bool isLoop = false) { var sound = SoundEventDictionary[soundName]; GameObject soundObj = LeanPool.Spawn(GameManager.instance.basePrefabs.audioEventObject); soundObj.transform.position = position; soundObj.name = String.Format("{0}-WwiseEvent", soundName); sound.Post(soundObj, (uint)AkCallbackType.AK_EndOfEvent, AutoDespawnCallback, soundObj); normalAudioPlayingIDs[soundName] = sound.PlayingId; } public void StopSoundFX(string soundName) { if (normalAudioPlayingIDs.TryGetValue(soundName, out uint playingID)) { Debug.Log("stop sound fx"); AkSoundEngine.StopPlayingID(playingID); } } public void StopSoundWithFadeOut(string soundName, float fadeOutDuration) { if (normalAudioPlayingIDs.TryGetValue(soundName, out uint playingID)) { AkSoundEngine.ExecuteActionOnPlayingID( AkActionOnEventType.AkActionOnEventType_Stop, playingID, (int)(fadeOutDuration * 1000), // 将秒数转为毫秒 AkCurveInterpolation.AkCurveInterpolation_Sine // 选择淡出曲线 ); } } /// /// 自动回收临时音频对象 /// private void AutoDespawnCallback(object in_cookie, AkCallbackType in_type, AkCallbackInfo in_info) { if (in_type == AkCallbackType.AK_EndOfEvent) { GameObject tempAudioObject = in_cookie as GameObject; if (tempAudioObject != null) { LeanPool.Despawn(tempAudioObject); } } } private void OnEventCallback(object in_cookie, AkCallbackType in_type, AkCallbackInfo in_info) { if (in_type == AkCallbackType.AK_EndOfEvent) { if (in_cookie is string soundName) normalAudioPlayingIDs.Remove(soundName); } } } }