popcorn/Scripts/Managers/SoundManager.cs

575 lines
21 KiB
C#

using UnityEngine;
using UnityEngine.Audio;
using System;
using System.Collections;
using System.Collections.Generic;
public enum SoundType{
BGM,
SE,
Voice,
}
public class SoundManager : SingletonMonoBehaviour<SoundManager> {
private string bgmFilePath = "";
private AudioSource bgmSource = null;
private float uniqueBGMVolume;
public float UniqueBGMVolume {
get{ return uniqueBGMVolume; }
}
private List<PlayingAudio> seSourceList = new List<PlayingAudio>();
private Dictionary<string, PlayingAudio> seLoopSourceDic = new Dictionary<string, PlayingAudio>();
private List<PlayingAudio> voiceSourceList = new List<PlayingAudio>();
public AudioMixerGroup defaultBGMAudioMixer;
public AudioMixerGroup defaultSEAudioMixer;
public AudioMixerGroup defaultVoiceAudioMixer;
public float bgmVolume = 1.0f;
public float seVolume = 1.0f;
public float voiceVolume = 1.0f;
public float pauseTime = 0.0f;
public float GetVolume(SoundType soundType){
switch(soundType){
case SoundType.BGM:
return bgmVolume;
case SoundType.Voice:
return voiceVolume;
default:
return seVolume;
}
}
[SerializeField]
private bool enabledBGM = true;
[SerializeField]
private bool enabledSE = true;
[SerializeField]
private bool enabledVoice = true;
public void EnabledSound(SoundType soundType, bool enabled){
switch(soundType){
case SoundType.BGM:
enabledBGM = enabled;
break;
case SoundType.Voice:
enabledVoice = enabled;
break;
default:
enabledSE = enabled;
break;
}
}
public bool IsEnabled(SoundType soundType){
switch(soundType){
case SoundType.BGM:
return enabledBGM;
case SoundType.Voice:
return enabledVoice;
default:
return enabledSE;
}
}
void Awake(){
if(CheckInstance()){
return;
}
#if !OLD_STORAGE
enabledBGM = UsayaStorageManager.LoadOrDefault<bool>(UsayaStorageFilename.Settings_Data, "EnabledBGM", true);
enabledSE = UsayaStorageManager.LoadOrDefault<bool>(UsayaStorageFilename.Settings_Data, "EnabledSE", true);
enabledVoice = UsayaStorageManager.LoadOrDefault<bool>(UsayaStorageFilename.Settings_Data, "EnabledVoice", true);
bgmVolume = UsayaStorageManager.LoadOrDefault<float>(UsayaStorageFilename.Settings_Data, "VolumeBGM", bgmVolume);
seVolume = UsayaStorageManager.LoadOrDefault<float>(UsayaStorageFilename.Settings_Data, "VolumeSE", seVolume);
voiceVolume = UsayaStorageManager.LoadOrDefault<float>(UsayaStorageFilename.Settings_Data, "VolumeVoice", voiceVolume);
#else
if(UsayaStorageManager.Exists(UsayaStorageFilename.Settings_Data, "EnabledBGM")){
enabledBGM = UsayaStorageManager.Load<bool>(UsayaStorageFilename.Settings_Data, "EnabledBGM");
}else{
try{
if(StorageManager.Exists(StorageFilename.SettingsData, "EnabledBGM")){
enabledBGM = StorageManager.Load<bool>(StorageFilename.SettingsData, "EnabledBGM");
}else{
enabledBGM = DataManager.LoadOrDefault<bool>("EnabledBGM", true);
}
}catch{
enabledBGM = DataManager.LoadOrDefault<bool>("EnabledBGM", true);
}
}
if(UsayaStorageManager.Exists(UsayaStorageFilename.Settings_Data, "EnabledSE")){
enabledSE = UsayaStorageManager.Load<bool>(UsayaStorageFilename.Settings_Data, "EnabledSE");
}else{
try{
if(StorageManager.Exists(StorageFilename.SettingsData, "EnabledSE")){
enabledSE = StorageManager.Load<bool>(StorageFilename.SettingsData, "EnabledSE");
}else{
enabledSE = DataManager.LoadOrDefault<bool>("EnabledSE", true);
}
}catch{
enabledSE = DataManager.LoadOrDefault<bool>("EnabledSE", true);
}
}
if(UsayaStorageManager.Exists(UsayaStorageFilename.Settings_Data, "EnabledVoice")){
enabledVoice = UsayaStorageManager.Load<bool>(UsayaStorageFilename.Settings_Data, "EnabledVoice");
}else{
try{
if(StorageManager.Exists(StorageFilename.SettingsData, "EnabledVoice")){
enabledVoice = StorageManager.Load<bool>(StorageFilename.SettingsData, "EnabledVoice");
}else{
enabledVoice = DataManager.LoadOrDefault<bool>("EnabledVoice", true);
}
}catch{
enabledVoice = DataManager.LoadOrDefault<bool>("EnabledVoice", true);
}
}
if(UsayaStorageManager.Exists(UsayaStorageFilename.Settings_Data, "VolumeBGM")){
bgmVolume = UsayaStorageManager.Load<float>(UsayaStorageFilename.Settings_Data, "VolumeBGM");
}else{
try{
if(StorageManager.Exists(StorageFilename.SettingsData, "VolumeBGM")){
bgmVolume = StorageManager.Load<float>(StorageFilename.SettingsData, "VolumeBGM");
}else{
bgmVolume = DataManager.LoadOrDefault<float>("VolumeBGM", bgmVolume);
}
}catch{
bgmVolume = DataManager.LoadOrDefault<float>("VolumeBGM", bgmVolume);
}
}
if(UsayaStorageManager.Exists(UsayaStorageFilename.Settings_Data, "VolumeSE")){
seVolume = UsayaStorageManager.Load<float>(UsayaStorageFilename.Settings_Data, "VolumeSE");
}else{
try{
if(StorageManager.Exists(StorageFilename.SettingsData, "VolumeSE")){
seVolume = StorageManager.Load<float>(StorageFilename.SettingsData, "VolumeSE");
}else{
seVolume = DataManager.LoadOrDefault<float>("VolumeSE", seVolume);
}
}catch{
seVolume = DataManager.LoadOrDefault<float>("VolumeSE", seVolume);
}
}
if(UsayaStorageManager.Exists(UsayaStorageFilename.Settings_Data, "VolumeVoice")){
voiceVolume = UsayaStorageManager.Load<float>(UsayaStorageFilename.Settings_Data, "VolumeVoice");
}else{
try{
if(StorageManager.Exists(StorageFilename.SettingsData, "VolumeVoice")){
voiceVolume = StorageManager.Load<float>(StorageFilename.SettingsData, "VolumeVoice");
}else{
voiceVolume = DataManager.LoadOrDefault<float>("VolumeVoice", voiceVolume);
}
}catch{
voiceVolume = DataManager.LoadOrDefault<float>("VolumeVoice", voiceVolume);
}
}
#endif
}
public void SaveEnabledBGM(bool enabled){
UsayaStorageManager.Save(UsayaStorageFilename.Settings_Data, "EnabledBGM", enabled);
enabledBGM = enabled;
if(bgmSource != null){
bgmSource.mute = !enabledBGM;
}
}
public void SaveEnabledSE(bool enabled){
UsayaStorageManager.Save(UsayaStorageFilename.Settings_Data, "EnabledSE", enabled);
enabledSE = enabled;
seSourceList.ForEach(se => se.ChangeMute(!enabledSE));
}
public void SaveVolumeBGM(){
SaveVolumeBGM(bgmVolume);
}
public void SaveVolumeBGM(float volume){
UsayaStorageManager.Save(UsayaStorageFilename.Settings_Data, "VolumeBGM", volume);
ChangeVolumeBGM(volume);
}
public void ChangeVolumeBGM(float volume){
bgmVolume = volume;
if(bgmSource != null){
bgmSource.volume = uniqueBGMVolume * volume;
bgmSource.mute = bgmSource.volume <= 0.0f;
}
}
public void ChangeVolumeUniqueBGM(float volume){
uniqueBGMVolume = volume;
if(bgmSource != null){
bgmSource.volume = uniqueBGMVolume * bgmVolume;
}
}
public void SaveVolumeSE(){
SaveVolumeSE(seVolume);
}
public void SaveVolumeSE(float volume){
UsayaStorageManager.Save(UsayaStorageFilename.Settings_Data, "VolumeSE", volume);
ChangeVolumeSE(volume);
}
public void ChangeVolumeSE(float volume){
seVolume = volume;
seSourceList.ForEach(se => se.ChangeVolume(volume));
foreach(KeyValuePair<string, PlayingAudio> pair in seLoopSourceDic){
pair.Value.ChangeVolume(volume);
}
}
public void SaveVolumeVoice(){
SaveVolumeVoice(voiceVolume);
}
public void SaveVolumeVoice(float volume){
UsayaStorageManager.Save(UsayaStorageFilename.Settings_Data, "VolumeVoice", volume);
ChangeVolumeVoice(volume);
}
public void ChangeVolumeVoice(float volume){
voiceVolume = volume;
voiceSourceList.ForEach(voice => voice.ChangeVolume(volume));
}
public void ChangeVolume(SoundType soundType, float volume){
switch(soundType){
case SoundType.BGM:
ChangeVolumeBGM(volume);
break;
case SoundType.Voice:
ChangeVolumeVoice(volume);
break;
default:
ChangeVolumeSE(volume);
break;
}
}
void LateUpdate(){
for(int i = seSourceList.Count - 1; i >= 0; --i){
if(!seSourceList[i].IsPlaying()){
seSourceList[i].PlayCallBack();
seSourceList.RemoveAt(i);
}
}
for(int i = voiceSourceList.Count - 1; i >= 0; --i){
if(!voiceSourceList[i].IsPlaying()){
voiceSourceList[i].PlayCallBack();
voiceSourceList.RemoveAt(i);
}
}
}
public void PauseBGM() {
if(bgmSource) bgmSource.Pause();
}
public void UnPauseBGM() {
if(bgmSource) bgmSource.UnPause();
}
public void PauseTimeBGM() {
if(bgmSource){
pauseTime = bgmSource.time;
bgmSource.Pause();
}
}
public void UnPauseTimeBGM() {
if(bgmSource){
bgmSource.UnPause();
bgmSource.time = pauseTime;
}
}
public void ReplayBGM(){
if(!bgmSource) return ;
bgmSource.Stop();
bgmSource.Play();
}
public void StopBGM(){
if(!bgmSource) return ;
bgmFilePath = "";
bgmSource.Stop();
bgmSource.clip = null;
}
public void StopSE(){
foreach(PlayingAudio playing in seSourceList){
playing.Stop();
}
seSourceList.Clear();
}
public void StopSELoop(){
foreach(KeyValuePair<string, PlayingAudio> pair in seLoopSourceDic){
pair.Value.StopDestroy();
}
seLoopSourceDic.Clear();
}
public void StopSELoop(string filePath){
if(!seLoopSourceDic.ContainsKey(filePath)) return ;
PlayingAudio audioSource = seLoopSourceDic[filePath];
audioSource.StopDestroy();
seLoopSourceDic.Remove(filePath);
}
public void StopVoice(){
foreach(PlayingAudio playing in voiceSourceList){
playing.Stop();
}
voiceSourceList.Clear();
}
public void StopAll(){
StopBGM();
StopSE();
StopSELoop();
StopVoice();
}
public void StopAllFade(float interval){
FadeOut(interval, StopAll);
}
public void ChangeFadeBGM(string filePath, float interval, float volume = 1.0f, bool loop = true){
if(bgmFilePath.Contains(filePath)) return ;
if(bgmFilePath.Length > 0){
FadeOut(interval * 0.5f, () => {
PlayBGM(filePath, volume);
FadeIn(interval * 0.5f, ActionExtensions.EmptyAction);
});
}else{
PlayBGM(filePath, volume, loop);
}
}
public void PlayBGM(string filePath, float volume = 1.0f, bool loop = true){
if(bgmFilePath.Contains(filePath)) return ;
bgmFilePath = filePath;
PlayBGM(LoadAudioClip(filePath, SoundType.BGM), volume, loop);
}
public void PlayBGM(AudioClip clip, float volume = 1.0f, bool loop = true){
if(bgmSource == null){
bgmSource = gameObject.AddComponent<AudioSource>();
}
if(bgmSource.clip == clip) return ;
uniqueBGMVolume = volume;
pauseTime = 0.0f;
bgmSource.time = 0.0f;
bgmSource.Stop();
bgmSource.clip = clip;
bgmSource.loop = loop;
bgmSource.volume = uniqueBGMVolume * bgmVolume;
bgmSource.mute = !enabledBGM;
bgmSource.Play();
bgmSource.outputAudioMixerGroup = defaultBGMAudioMixer;
}
public void PlaySE(string filePath, int maxCount = 0, float volume = 1.0f, float pitch = 1.0f){
PlaySE(LoadAudioClip(filePath, SoundType.SE), maxCount, volume, pitch);
}
public void PlaySE(AudioClip clip, int maxCount = 0, float volume = 1.0f, float pitch = 1.0f){
if(clip == null) return ;
PlaySE(clip, ActionExtensions.EmptyAction, maxCount, volume, pitch);
}
public void PlaySE(string filePath, Action callBack, int maxCount = 0, float volume = 1.0f){
PlaySE(LoadAudioClip(filePath, SoundType.SE), callBack, maxCount, volume);
}
public void PlaySE(AudioClip clip, Action callBack, int maxCount = 0, float volume = 1.0f, float pitch = 1.0f){
if(clip == null || isPausing) return ;
PlaySE(clip, maxCount, volume, pitch, callBack, seSourceList);
}
private void PlaySE(AudioClip clip, int maxCount, float volume, float pitch, Action callBack, List<PlayingAudio> list){
string clipName = clip.name;
var result = FindCountOverPlayingAudio(clipName, maxCount, list);
if(result != null){
result.audioSource.Stop();
result.audioSource.Play();
}else{
AudioSource source = CreateAudioSource(clip, volume * seVolume, pitch, !enabledSE, defaultSEAudioMixer);
list.Add(new PlayingAudio(clipName, source, volume, callBack));
}
}
public AudioSource PlaySELoop(string filePath, float volume = 1.0f, float pitch = 1.0f){
if(seLoopSourceDic.ContainsKey(filePath)) return seLoopSourceDic[filePath].audioSource;
AudioClip clip = LoadAudioClip(filePath, SoundType.SE);
AudioSource source = CreateAudioSource(clip, volume * seVolume, pitch, !enabledSE, defaultSEAudioMixer);
source.loop = true;
seLoopSourceDic.Add(filePath, new PlayingAudio(clip.name, source, volume, ActionExtensions.EmptyAction));
return source;
}
public void PlayVoice(string filePath, int maxCount = 0, float volume = 1.0f, float pitch = 1.0f){
PlayVoice(LoadAudioClip(filePath, SoundType.Voice), maxCount, volume, pitch);
}
public void PlayVoice(AudioClip clip, int maxCount = 0, float volume = 1.0f, float pitch = 1.0f){
if(clip == null) return ;
PlayVoice(clip, ActionExtensions.EmptyAction, maxCount, volume, pitch);
}
public void PlayVoice(string filePath, Action callBack, int maxCount = 0, float volume = 1.0f){
PlayVoice(LoadAudioClip(filePath, SoundType.Voice), callBack, maxCount, volume);
}
public void PlayVoice(AudioClip clip, Action callBack, int maxCount = 0, float volume = 1.0f, float pitch = 1.0f){
if(clip == null || isPausing){
callBack();
}else{
PlayVoice(clip, maxCount, volume, pitch, callBack, voiceSourceList);
}
}
private void PlayVoice(AudioClip clip, int maxCount, float volume, float pitch, Action callBack, List<PlayingAudio> list){
string clipName = clip.name;
var result = FindCountOverPlayingAudio(clipName, maxCount, list);
if(result != null){
result.audioSource.Stop();
result.audioSource.Play();
}else{
AudioSource source = CreateAudioSource(clip, volume * voiceVolume, pitch, !enabledVoice, defaultVoiceAudioMixer);
list.Add(new PlayingAudio(clipName, source, volume, callBack));
}
}
private PlayingAudio FindCountOverPlayingAudio(string clipName, int maxCount, List<PlayingAudio> list){
if(maxCount > 0){
int counter = 0;
foreach(var pa in list){
if(pa.Name == clipName && ++counter >= maxCount){
foreach(var p in list){
if(p.Name == clipName){
return p;
}
}
}
}
}
return null;
}
private AudioSource CreateAudioSource(AudioClip clip, float volume, float pitch, bool mute, AudioMixerGroup audioMixerGroup){
AudioSource source = gameObject.AddComponent<AudioSource>();
source.Stop();
source.clip = clip;
source.volume = volume;
source.pitch = pitch;
source.mute = mute;
source.Play();
source.outputAudioMixerGroup = defaultVoiceAudioMixer;
return source;
}
public class PlayingAudio {
private string name;
public string Name {
get{ return name; }
}
public AudioSource audioSource = null;
private Action callBack = null;
private float uniqueVolume;
public PlayingAudio(string name, AudioSource audioSource, float uniqueVolume, Action callBack){
this.name = name;
this.audioSource = audioSource;
this.uniqueVolume = uniqueVolume;
this.callBack = callBack;
}
public bool IsPlaying(){
return audioSource.isPlaying;
}
public void PlayCallBack(){
callBack();
Destroy(audioSource);
}
public void Stop(){
audioSource.Stop();
}
public void StopDestroy(){
audioSource.Stop();
Destroy(audioSource);
}
public void ChangeVolume(float volume){
audioSource.volume = volume * uniqueVolume;
}
public void ChangeMute(bool mute){
audioSource.mute = mute;
}
}
private Dictionary<string, AudioClip> audioClipDict = new Dictionary<string, AudioClip>();
private AudioClip LoadAudioClip(string filePath, SoundType soundType){
if(!filePath.Contains("/")){
switch(soundType){
case SoundType.BGM: filePath = "Sounds/BGM/" + filePath; break;
case SoundType.SE: filePath = "Sounds/SE/" + filePath; break;
case SoundType.Voice: filePath = "Sounds/Voice/" + filePath; break;
}
}
AudioClip result = null;
if(!audioClipDict.TryGetValue(filePath, out result)){
result = Resources.Load(filePath, typeof(AudioClip)) as AudioClip;
#if UNITY_EDITOR
if(result == null){
Debug.LogError("鳴らそうとしているファイル(" + filePath + ")が存在しません。");
UnityEditor.EditorApplication.isPlaying = false;
}
#endif
audioClipDict.Add(filePath, result);
}
return result;
}
private void UpdateMute(){
if(bgmSource != null){
bgmSource.mute = !enabledBGM;
}
seSourceList.ForEach(se => se.ChangeMute(!enabledSE));
voiceSourceList.ForEach(voice => voice.ChangeMute(!enabledVoice));
}
public void ChangeBGMAudioMixerGroup(AudioMixerGroup amg){
bgmSource.outputAudioMixerGroup = amg;
}
public void ResetBGMAudioMixerGroup(){
bgmSource.outputAudioMixerGroup = defaultBGMAudioMixer;
}
private bool isPause = false;
void OnApplicationPause(bool pauseStatus){
if(!bgmSource) return ;
if(pauseStatus){
isPause = true;
bgmSource.volume = 0.0f;
PauseBGM();
isPausing = true;
}else if(isPause){
isPause = false;
StartCoroutine(ReturnPause());
}
}
private bool isPausing = false;
private IEnumerator ReturnPause(){
int i = 0;
// 素通りだと起動時にFadeIn後のVolumeから開始される
int waitFrameCounter = 20;
while(i++ < waitFrameCounter){
yield return null;
}
isPausing = false;
UnPauseBGM();
FadeIn(1.0f, ActionExtensions.EmptyAction);
}
private void FadeIn(float duration, Action callback){
Fade(duration, lerp => Mathf.Lerp(0.0f, 1.0f, lerp * lerp), callback);
}
private void FadeOut(float duration, Action callback){
Fade(duration, lerp => 1.0f - Mathf.Lerp(0.0f, 1.0f, lerp * lerp), callback);
}
private void Fade(float duration, Func<float, float> lerpToVolume, Action callback){
this.CallLerpSmooth(duration, lerp => {
float v = lerpToVolume(lerp);
bgmSource.volume = v * uniqueBGMVolume * bgmVolume;
float se = v * seVolume;
foreach(PlayingAudio playing in seSourceList){
playing.ChangeVolume(se);
}
foreach(KeyValuePair<string, PlayingAudio> pair in seLoopSourceDic){
pair.Value.ChangeVolume(se);
}
float voice = v * voiceVolume;
foreach(PlayingAudio playing in voiceSourceList){
playing.ChangeVolume(voice);
}
}, callback);
}
}