Files
Cielonos/Assets/Scripts/SLSFramework/WwiseAssistance/AudioContainer.cs
SoulliesOfficial 33b1795c1f 更新
2026-01-03 18:19:39 -05:00

187 lines
6.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<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(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;
}
/// <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(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;
}
/// <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);
}
}
}
}
}