220 lines
7.6 KiB
C#
220 lines
7.6 KiB
C#
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<AudioManager>
|
||
{
|
||
[Title("Settings")]
|
||
[Required]
|
||
public GameObject audioPoint;
|
||
public List<Bank> soundBanks;
|
||
|
||
[Title("Subsystems")]
|
||
public BackgroundMusicManager backgroundMusicManager;
|
||
|
||
private static Dictionary<string, uint> _trackedPlayingIDs = new Dictionary<string, uint>();
|
||
|
||
protected override void Awake()
|
||
{
|
||
base.Awake();
|
||
soundBanks.ForEach(bank => bank.Load());
|
||
}
|
||
}
|
||
|
||
public partial class AudioManager
|
||
{
|
||
/// <summary>
|
||
/// 【核心方法】在指定位置播放 3D 音效
|
||
/// 使用方法: AudioManager.Instance.PlayEvent(AK.EVENTS.EXPLOSION, position);
|
||
/// </summary>
|
||
/// <param name="eventID">AK.EVENTS 中的静态 ID</param>
|
||
/// <param name="position">世界坐标</param>
|
||
/// <returns>返回 WwiseEmitter,以便需要时手动 Stop</returns>
|
||
public static AudioPoint Post(uint eventID, Vector3 position = default)
|
||
{
|
||
if (eventID == 0) return null;
|
||
|
||
AudioPoint point = LeanPool.Spawn(instance.audioPoint, position, Quaternion.identity).GetComponent<AudioPoint>();
|
||
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
|
||
);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 【新增】通过 Key 停止特定音效
|
||
/// </summary>
|
||
public static void Stop(string trackingKey, int fadeOutMs = 0)
|
||
{
|
||
if (_trackedPlayingIDs.TryGetValue(trackingKey, out uint playingID))
|
||
{
|
||
Stop(playingID, fadeOutMs);
|
||
_trackedPlayingIDs.Remove(trackingKey);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 【新增】停止所有被追踪的循环音效 (常用于切换场景前)
|
||
/// </summary>
|
||
public static void StopAllTrackedEvents(int fadeOutMs = 0)
|
||
{
|
||
foreach (var playingID in _trackedPlayingIDs.Values)
|
||
{
|
||
Stop(playingID, fadeOutMs);
|
||
}
|
||
_trackedPlayingIDs.Clear();
|
||
}
|
||
}
|
||
|
||
public partial class AudioManager
|
||
{
|
||
/// <summary>
|
||
/// 设置全局参数 (RTPC)
|
||
/// 例如: "MasterVolume", "MusicVolume", "PlayerHealth"
|
||
/// </summary>
|
||
public void SetRTPC(string rtpcName, float value)
|
||
{
|
||
AkUnitySoundEngine.SetRTPCValue(rtpcName, value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置状态 (State)
|
||
/// 例如: Group="MusicState", State="Combat" / "Explore"
|
||
/// </summary>
|
||
public void SetState(string stateGroup, string stateName)
|
||
{
|
||
AkUnitySoundEngine.SetState(stateGroup, stateName);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置全局开关 (Switch) - 通常用于特定的全局对象
|
||
/// </summary>
|
||
public void SetGlobalSwitch(string switchGroup, string switchName)
|
||
{
|
||
// 对于全局Switch,通常传一个全局GameObject,或者使用 Wwise 的 Global Scope
|
||
AkUnitySoundEngine.SetSwitch(switchGroup, switchName, gameObject);
|
||
}
|
||
}
|
||
} |