2025-06-03 02:42:28 -04:00
|
|
|
|
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<string, Event> SoundEventDictionary;
|
2025-07-08 14:28:40 -04:00
|
|
|
|
public Dictionary<string, RTPC> SoundRTPCDictionary;
|
2025-06-03 02:42:28 -04:00
|
|
|
|
private Dictionary<string, uint> normalAudioPlayingIDs;
|
|
|
|
|
|
|
|
|
|
|
|
private void Awake()
|
|
|
|
|
|
{
|
|
|
|
|
|
normalAudioPlayingIDs = new Dictionary<string, uint>();
|
|
|
|
|
|
SoundEventDictionary ??= new Dictionary<string, Event>();
|
2025-07-08 14:28:40 -04:00
|
|
|
|
SoundRTPCDictionary ??= new Dictionary<string, RTPC>();
|
2025-06-03 02:42:28 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void PostEvent(string eventName, GameObject attachedObject = null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Event evt = SoundEventDictionary[eventName];
|
|
|
|
|
|
attachedObject = attachedObject == null ? gameObject : attachedObject;
|
|
|
|
|
|
evt.Post(attachedObject);
|
|
|
|
|
|
}
|
2025-07-08 14:28:40 -04:00
|
|
|
|
|
|
|
|
|
|
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.");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-06-03 02:42:28 -04:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-07-08 14:28:40 -04:00
|
|
|
|
/// 依附于GameObject播放音频,attachedObject为null时默认为当前GameObject。
|
|
|
|
|
|
/// 在Wwise中设置音频的空间属性(2D或3D)。
|
2025-06-03 02:42:28 -04:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-07-08 14:28:40 -04:00
|
|
|
|
/// 在指定位置播放音频
|
|
|
|
|
|
/// 在Wwise中设置音频的空间属性(2D或3D)。
|
2025-06-03 02:42:28 -04:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
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 // 选择淡出曲线
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 自动回收临时音频对象
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|