Files
ichni_Official/Assets/Scripts/SLSUtilities/WwiseAssistance/AudioContainer.cs

186 lines
6.7 KiB
C#
Raw Normal View History

2026-03-14 03:13:10 -04:00
using System;
using System.Collections;
using System.Collections.Generic;
using Lean.Pool;
using Sirenix.OdinInspector;
using UniRx;
using UnityEngine;
using Event = AK.Wwise.Event;
namespace SLSUtilities.WwiseAssistance
{
public class AudioContainer : SerializedMonoBehaviour
{
public Dictionary<string, Event> soundEventDictionary = new Dictionary<string, Event>();
private HashSet<uint> normalAudioPlayingIDs;
private void Awake()
{
soundEventDictionary ??= new Dictionary<string, Event>();
normalAudioPlayingIDs = new HashSet<uint>();
}
/// <summary>
/// 触发自定义的Wwise事件
/// </summary>
public void PostEvent(string eventName, GameObject attachedObject = null)
{
Event evt = soundEventDictionary[eventName];
if (evt == null) return;
attachedObject = attachedObject == null ? gameObject : attachedObject;
evt.Post(attachedObject);
}
/// <summary>
/// 依附于GameObject播放3D音频attachedObject为null时默认为当前GameObject
/// </summary>
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(AudioManager.Instance.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;
}
/// <summary>
/// 在指定位置播放3D音频
/// </summary>
public uint PlaySoundFX(string soundName, Vector3 position, bool isLoop = false)
{
Event sound = soundEventDictionary[soundName];
if (sound == null) return 0;
GameObject soundObj = LeanPool.Spawn(AudioManager.Instance.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;
}
/// <summary>
/// 停止播放音效
/// </summary>
public void StopSoundFX(uint playingID)
{
if (normalAudioPlayingIDs.Contains(playingID))
{
AkUnitySoundEngine.StopPlayingID(playingID);
}
else
{
Debug.LogWarning($"No sound is playing with PlayingID: {playingID}");
}
}
/// <summary>
/// 以淡出效果停止播放音效
/// </summary>
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}");
}
}
/// <summary>
/// 自动回收临时音频对象
/// </summary>
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);
}
}
}
}
}