FMod
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
namespace AibisDream.Kit
|
||||
{
|
||||
public enum AmbState
|
||||
{
|
||||
Main,
|
||||
Clinic,
|
||||
Outside,
|
||||
Footbridge,
|
||||
Subway,
|
||||
Head,
|
||||
Memory,
|
||||
Eye,
|
||||
UF,
|
||||
Body,
|
||||
Engine,
|
||||
GearBox
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2cec528d61b846fc9d9791fca8d917ed
|
||||
timeCreated: 1741259362
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace AibisDream.Kit
|
||||
{
|
||||
public class AudioKit : Singleton<AudioKit>
|
||||
{
|
||||
public AudioPlayer MusicPlayer { get; private set; }
|
||||
public AudioPlayer VoicePlayer { get; private set; }
|
||||
|
||||
public override void OnSingletonInit()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff78cd5fd6a74902945f20346bc2036d
|
||||
timeCreated: 1726662840
|
||||
@@ -90,17 +90,6 @@ namespace AibisDream
|
||||
|
||||
#endregion
|
||||
|
||||
#region 播放唱歌
|
||||
|
||||
public void PlayVoice(string actorName, string voiceName)
|
||||
{
|
||||
AudioClip clip = RandomLoadAudioClip(3, $"Audio/{actorName}");
|
||||
_voiceSource.clip = clip;
|
||||
_voiceSource.Play();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 循环播放
|
||||
|
||||
[YarnCommand("play_loop_audio")]
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AibisDream.Kit
|
||||
{
|
||||
public class AudioPlayer : IPoolable, IPoolType
|
||||
{
|
||||
#region 对象池功能
|
||||
|
||||
public void OnRecycled()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsRecycled { get; set; }
|
||||
|
||||
public void Recycle2Cache()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c877314dfb3460d91eef3edfe2786c6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using FMOD.Studio;
|
||||
using Yarn.Unity;
|
||||
|
||||
namespace AibisDream.Kit
|
||||
{
|
||||
public static class AudioYarnCommand
|
||||
{
|
||||
private static IAudioManager AudioManager => FmodManager.Instance;
|
||||
|
||||
[YarnCommand("play_music")]
|
||||
public static void PlayMusic(string eventName)
|
||||
{
|
||||
AudioManager.PlayMusic(eventName);
|
||||
}
|
||||
|
||||
[YarnCommand("stop_music")]
|
||||
public static void StopMusic(string eventName, string type = null)
|
||||
{
|
||||
// 处理停止类型
|
||||
var mode = type switch
|
||||
{
|
||||
"fade" => STOP_MODE.ALLOWFADEOUT,
|
||||
_ => STOP_MODE.IMMEDIATE
|
||||
};
|
||||
|
||||
AudioManager.StopMusic(eventName, mode);
|
||||
}
|
||||
|
||||
[YarnCommand("set_music_param")]
|
||||
public static void SetMusicParam(string eventName, string paramName, float paramValue)
|
||||
{
|
||||
AudioManager.SetMusicParam(eventName, paramName, paramValue);
|
||||
}
|
||||
|
||||
[YarnCommand("play_sfx")]
|
||||
public static void PlaySfx(string eventName)
|
||||
{
|
||||
AudioManager.PlaySfx(eventName);
|
||||
}
|
||||
|
||||
[YarnCommand("stop_sfx")]
|
||||
public static void StopSfx(string eventName, string type = null)
|
||||
{
|
||||
// 处理停止类型
|
||||
var mode = type switch
|
||||
{
|
||||
"fade" => STOP_MODE.ALLOWFADEOUT,
|
||||
_ => STOP_MODE.IMMEDIATE
|
||||
};
|
||||
|
||||
AudioManager.StopSfx(eventName, mode);
|
||||
}
|
||||
|
||||
[YarnCommand("set_sfx_param")]
|
||||
public static void SetSfxParam(string eventName, string paramName, float paramValue)
|
||||
{
|
||||
AudioManager.SetSfxParam(eventName, paramName, paramValue);
|
||||
}
|
||||
|
||||
[YarnCommand("change_amb")]
|
||||
public static void ChangeAmb(string ambState)
|
||||
{
|
||||
var realState = Enum.Parse<AmbState>(ambState);
|
||||
AudioManager.ChangeAmb(realState);
|
||||
}
|
||||
|
||||
[YarnCommand("set_amb_param")]
|
||||
public static void SetAmbParam(string paramName, float value)
|
||||
{
|
||||
AudioManager.SetAmbParam(paramName, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c2c66883a8f4acda0263f7453bd4cd2
|
||||
timeCreated: 1741257321
|
||||
@@ -0,0 +1,35 @@
|
||||
using FMOD.Studio;
|
||||
using FMODUnity;
|
||||
|
||||
namespace AibisDream.Kit
|
||||
{
|
||||
public static class FModEx
|
||||
{
|
||||
public static bool IsPlaying(this EventInstance instance)
|
||||
{
|
||||
if (!instance.isValid()) return false;
|
||||
|
||||
instance.getPlaybackState(out var playbackState);
|
||||
return playbackState == PLAYBACK_STATE.PLAYING;
|
||||
}
|
||||
|
||||
public static PLAYBACK_STATE GetPlayBackState(this EventInstance instance)
|
||||
{
|
||||
instance.getPlaybackState(out var playbackState);
|
||||
return playbackState;
|
||||
}
|
||||
|
||||
public static EventDescription GetDescription(this EventInstance instance)
|
||||
{
|
||||
instance.getDescription(out var description);
|
||||
return description;
|
||||
}
|
||||
|
||||
public static bool IsEventExist(string eventPath)
|
||||
{
|
||||
var result = RuntimeManager.StudioSystem.getEvent(eventPath, out _);
|
||||
|
||||
return result == FMOD.RESULT.OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf7b32b854524cf9bb65c552e7050830
|
||||
timeCreated: 1741319049
|
||||
@@ -1,13 +1,267 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using AibisDream.FixSystem;
|
||||
using AibisDream.Framework;
|
||||
using FMOD;
|
||||
using FMOD.Studio;
|
||||
using FMODUnity;
|
||||
using UnityEngine;
|
||||
using STOP_MODE = FMOD.Studio.STOP_MODE;
|
||||
|
||||
namespace AibisDream.Kit
|
||||
{
|
||||
public class FmodManager : Singleton<FmodManager>
|
||||
public class FmodManager : Singleton<FmodManager>, IAudioManager
|
||||
{
|
||||
public EventReference sound;
|
||||
private const string AmbStateName = "scene";
|
||||
|
||||
public string ambPath;
|
||||
|
||||
#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(FormatEventPath(ambPath));
|
||||
_ambInstance.start();
|
||||
}
|
||||
|
||||
public void ChangeAmb(AmbState state)
|
||||
{
|
||||
_ambInstance.setParameterByName(AmbStateName, (float)state);
|
||||
}
|
||||
|
||||
public void SetAmbParam(string paramName, float value)
|
||||
{
|
||||
_ambInstance.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)
|
||||
{
|
||||
var eventPath = FormatEventPath(eventName);
|
||||
if (_musicDict.TryGetValue(eventPath, out var oldMusic))
|
||||
{
|
||||
oldMusic.start();
|
||||
}
|
||||
else
|
||||
{
|
||||
var newMusic = RuntimeManager.CreateInstance(eventPath);
|
||||
_musicDict[eventPath] = newMusic;
|
||||
newMusic.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void StopMusic(string eventName, STOP_MODE stopMode)
|
||||
{
|
||||
var eventPath = FormatEventPath(eventName);
|
||||
if (_musicDict.TryGetValue(eventPath, out var oldMusic))
|
||||
{
|
||||
oldMusic.stop(stopMode);
|
||||
oldMusic.release();
|
||||
_musicDict.Remove(eventPath);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetMusicParam(string eventName, string param, float paramValue)
|
||||
{
|
||||
var eventPath = FormatEventPath(eventName);
|
||||
if (_musicDict.TryGetValue(eventPath, 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)
|
||||
{
|
||||
var eventPath = FormatEventPath(eventName);
|
||||
if (_sfxDict.TryGetValue(eventPath, out var oldSfx))
|
||||
{
|
||||
oldSfx.start();
|
||||
}
|
||||
else
|
||||
{
|
||||
var newSfx = RuntimeManager.CreateInstance(eventPath);
|
||||
if (newSfx.GetDescription().isOneshot(out var isOneshot) != RESULT.OK || !isOneshot)
|
||||
{
|
||||
_sfxDict[eventPath] = newSfx;
|
||||
}
|
||||
|
||||
newSfx.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void StopSfx(string eventName, STOP_MODE stopMode)
|
||||
{
|
||||
var eventPath = FormatEventPath(eventName);
|
||||
if (_sfxDict.TryGetValue(eventPath, out var oldSfx))
|
||||
{
|
||||
oldSfx.stop(stopMode);
|
||||
oldSfx.release();
|
||||
_musicDict.Remove(eventPath);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetSfxParam(string eventName, string paramName, float paramValue)
|
||||
{
|
||||
var eventPath = FormatEventPath(eventName);
|
||||
if (_sfxDict.TryGetValue(eventPath, out var sfx))
|
||||
{
|
||||
sfx.setParameterByName(paramName, paramValue);
|
||||
}
|
||||
}
|
||||
|
||||
#region 一些静态方法
|
||||
|
||||
private static string FormatEventPath(string eventName)
|
||||
{
|
||||
return $"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,
|
||||
_ => 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);
|
||||
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 SetAmbParam(string paramName, float value);
|
||||
|
||||
// 语音相关
|
||||
public void OnLineStart(DialogText dialogText);
|
||||
public void OnLineShown();
|
||||
|
||||
// 交互相关
|
||||
public void PlaySfx(string eventName);
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,19 @@ namespace AibisDream.Kit
|
||||
{
|
||||
return string.IsNullOrEmpty(nameColor) ? cn : $"<color={nameColor}>{cn}</color>";
|
||||
}
|
||||
|
||||
public string VoicePath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!voicePath.StartsWith("event:/"))
|
||||
{
|
||||
return "event:/" + voicePath;
|
||||
}
|
||||
|
||||
return voicePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum ActorRole
|
||||
|
||||
Reference in New Issue
Block a user