Files
aibis-dream/Assets/Scripts/Framework/AudioKit/AudioManager.cs
T
2025-03-10 15:49:52 +08:00

268 lines
8.1 KiB
C#

using System.Collections.Generic;
using AibisDream.FixSystem;
using AibisDream.Framework;
using FMOD;
using FMOD.Studio;
using FMODUnity;
using STOP_MODE = FMOD.Studio.STOP_MODE;
namespace AibisDream.Kit
{
public class AudioManager : Singleton<AudioManager>, IAudioManager
{
private const string AmbStateName = "scene";
public EventReference ambEvent;
#region Event实例
private EventInstance _ambInstance;
private EventInstance _voiceInstance;
private readonly Dictionary<string, EventInstance> _musicDict = new();
private readonly Dictionary<string, EventInstance> _sfxDict = new();
#endregion
#region 事件索引
private List<IUnRegister> _removeTrigger;
#endregion
private void Start()
{
// 注册事件
RegisterEvent();
// 启动AMB
InitAmb();
}
private void RegisterEvent()
{
// 语音相关
EnumEventSystem.Global.Register<DialogEventEnum, DialogText>(DialogEventEnum.LineStart, OnLineStart);
EnumEventSystem.Global.Register(DialogEventEnum.LineShown, OnLineShown);
// 场景切换相关
EnumEventSystem.Global.Register<EventEnum, string>(EventEnum.SceneLoad, OnSceneLoad);
EnumEventSystem.Global.Register<EventEnum, FixState>(EventEnum.FixStateSwitch, OnFixStateChange);
EnumEventSystem.Global.Register(EventEnum.SceneUnload, OnSceneUnload);
}
#region AMB相关
private void InitAmb()
{
_ambInstance = RuntimeManager.CreateInstance(ambEvent);
_ambInstance.start();
}
public void ChangeAmb(AmbState state)
{
RuntimeManager.StudioSystem.setParameterByName(AmbStateName, (float)state);
}
public void SetGlobalParam(string paramName, float value)
{
RuntimeManager.StudioSystem.setParameterByName(paramName, value);
}
private void OnSceneLoad(string loadingScene)
{
// 场景加载时切换AMB
var state = MatchAmbState(loadingScene);
ChangeAmb(state);
}
private void OnSceneUnload()
{
ChangeAmb(AmbState.Main);
}
private void OnFixStateChange(FixState nextState)
{
// 状态切换时加载
var state = MatchAmbState(nextState);
ChangeAmb(state);
}
#endregion
#region 音乐相关
public void PlayMusic(string eventName, string audioKey = null)
{
var eventPath = FormatEventPath(eventName);
var key = string.IsNullOrEmpty(audioKey) ? eventName : audioKey;
if (_musicDict.TryGetValue(key, out var oldMusic))
{
oldMusic.stop(STOP_MODE.IMMEDIATE);
oldMusic.release();
_musicDict.Remove(key);
}
var newMusic = RuntimeManager.CreateInstance(eventPath);
_musicDict[key] = newMusic;
newMusic.start();
}
public void StopMusic(string key, STOP_MODE stopMode)
{
if (_musicDict.TryGetValue(key, out var oldMusic))
{
oldMusic.stop(stopMode);
oldMusic.release();
_musicDict.Remove(key);
}
}
public void SetMusicParam(string key, string param, float paramValue)
{
if (_musicDict.TryGetValue(key, out var music))
{
music.setParameterByName(param, paramValue);
}
}
#endregion
public void OnLineStart(DialogText dialogText)
{
if (_voiceInstance.IsPlaying())
{
_voiceInstance.stop(STOP_MODE.IMMEDIATE);
_voiceInstance.release();
}
if (string.IsNullOrEmpty(dialogText.actor.voicePath) || !FModEx.IsEventExist(dialogText.actor.VoicePath))
{
return;
}
_voiceInstance = RuntimeManager.CreateInstance(dialogText.actor.VoicePath);
_voiceInstance.start();
}
public void OnLineShown()
{
if (_voiceInstance.isValid())
{
_voiceInstance.stop(STOP_MODE.IMMEDIATE);
_voiceInstance.release();
}
}
public void PlaySfx(string eventName, string audioKey = null)
{
var eventPath = FormatEventPath(eventName);
var key = string.IsNullOrEmpty(audioKey) ? eventName : audioKey;
if (_sfxDict.TryGetValue(key, out var oldSfx))
{
oldSfx.stop(STOP_MODE.IMMEDIATE);
oldSfx.release();
_sfxDict.Remove(key);
}
var newSfx = RuntimeManager.CreateInstance(eventPath);
if (newSfx.GetDescription().isOneshot(out var isOneshot) != RESULT.OK || !isOneshot)
{
_sfxDict[key] = newSfx;
}
newSfx.start();
}
public void StopSfx(string key, STOP_MODE stopMode)
{
if (_sfxDict.TryGetValue(key, out var oldSfx))
{
oldSfx.stop(stopMode);
oldSfx.release();
_musicDict.Remove(key);
}
}
public void SetSfxParam(string key, string paramName, float paramValue)
{
if (_sfxDict.TryGetValue(key, out var sfx))
{
sfx.setParameterByName(paramName, paramValue);
}
}
#region 一些静态方法
private static string FormatEventPath(string eventName)
{
return eventName.StartsWith("event:/") ? eventName : $"event:/{eventName}";
}
private static AmbState MatchAmbState(string key)
{
return key switch
{
"ExpressFixScene" => AmbState.Clinic,
"ShitouHeadiFixScene" => AmbState.Clinic,
"PeipeiFixScene" => AmbState.Clinic,
"Bridge" => AmbState.Footbridge,
"SkyBridge" => AmbState.Footbridge,
"SubWay" => AmbState.Subway,
"ClinicOut" => AmbState.Outside,
"OutSideSceneTemp" => AmbState.Outside,
_ => AmbState.Main
};
}
private static AmbState MatchAmbState(FixState fixState)
{
return fixState switch
{
FixState.Clinic => AmbState.Clinic,
FixState.Engine => AmbState.Engine,
FixState.BodyModule => AmbState.Body,
FixState.Gear => AmbState.GearBox,
FixState.UF => AmbState.UF,
FixState.Eye => AmbState.Eye,
FixState.Memory => AmbState.Memory,
_ => AmbState.Main
};
}
#endregion
}
public interface IAudioManager
{
// Yarn音频接口
public void PlayMusic(string eventName, string audioKey);
public void StopMusic(string eventName, STOP_MODE stopMode);
public void SetMusicParam(string eventName, string paramName, float paramValue);
// AMB参数变化
public void ChangeAmb(AmbState state);
public void SetGlobalParam(string paramName, float value);
// 语音相关
public void OnLineStart(DialogText dialogText);
public void OnLineShown();
// 交互相关
public void PlaySfx(string eventName, string audioKey);
public void StopSfx(string eventName, STOP_MODE stopMode);
public void SetSfxParam(string eventName, string paramName, float paramValue);
}
public class AudioData : IData
{
public string ambState;
public List<string> sfxNames = new();
public List<string> musicNames = new();
public void Load()
{
throw new System.NotImplementedException();
}
}
}