CapersProject/Assets/02.Scripts/Audio/AudioManager.cs

228 lines
7.2 KiB
C#
Raw Normal View History

2024-06-03 18:26:03 +00:00
using System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.SceneManagement;
namespace BlueWater.Audios
{
public class AudioManager : Singleton<AudioManager>
{
[Title("오디오 데이터")]
[SerializeField]
private BgmDataSo _bgmDataSo;
[SerializeField]
private SfxDataSo _sfxDataSo;
[SerializeField]
private int _sfxChannelCount = 32;
2024-06-03 18:26:03 +00:00
[Title("오디오 믹서")]
[SerializeField]
private AudioMixer _audioMixer;
[SerializeField]
private AudioMixerGroup _masterMixerGroup;
[SerializeField]
private AudioMixerGroup _bgmMixerGroup;
[SerializeField]
private AudioMixerGroup _sfxMixerGroup;
[Title("중복 사운드 처리")]
[SerializeField, Range(0f, 1f)]
private float _sfxMinInterval = 0.09f;
2024-06-03 18:26:03 +00:00
private Dictionary<string, AudioClip> _bgmDictionary;
private Dictionary<string, AudioClip> _sfxDictionary;
2024-06-03 18:26:03 +00:00
private AudioSource _bgmAudioSource;
private Dictionary<AudioSource, float> _sfxPitchDictionary;
private Dictionary<string, float> _sfxPlayTimeDictionary;
2024-06-03 18:26:03 +00:00
protected override void OnAwake()
{
InitializeDictionary();
InitializeComponents();
2024-06-03 18:26:03 +00:00
SceneManager.sceneLoaded += OnSceneLoaded;
}
private void OnDestroy()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
StopBgm();
StopSfxAll();
}
private void InitializeDictionary()
2024-06-03 18:26:03 +00:00
{
_bgmDictionary = new Dictionary<string, AudioClip>(_bgmDataSo.BgmDataList.Count);
foreach (var element in _bgmDataSo.BgmDataList)
2024-06-03 18:26:03 +00:00
{
_bgmDictionary.Add(element.BgmName, element.Clip);
2024-06-03 18:26:03 +00:00
}
_sfxDictionary = new Dictionary<string, AudioClip>(_sfxDataSo.SfxDataList.Count);
foreach (var element in _sfxDataSo.SfxDataList)
2024-06-03 18:26:03 +00:00
{
_sfxDictionary.Add(element.SfxName, element.Clip);
2024-06-03 18:26:03 +00:00
}
_sfxPlayTimeDictionary = new Dictionary<string, float>(_sfxDataSo.SfxDataList.Count);
2024-06-03 18:26:03 +00:00
}
private void InitializeComponents()
2024-06-03 18:26:03 +00:00
{
_bgmAudioSource = gameObject.AddComponent<AudioSource>();
_bgmAudioSource.outputAudioMixerGroup = _bgmMixerGroup;
_bgmAudioSource.loop = true;
2024-06-03 18:26:03 +00:00
_sfxPitchDictionary = new Dictionary<AudioSource, float>(_sfxChannelCount);
for (var i = 0; i < _sfxChannelCount; i++)
2024-06-03 18:26:03 +00:00
{
var sfxAudioSource = gameObject.AddComponent<AudioSource>();
sfxAudioSource.outputAudioMixerGroup = _sfxMixerGroup;
2024-06-03 18:26:03 +00:00
sfxAudioSource.loop = false;
_sfxPitchDictionary[sfxAudioSource] = sfxAudioSource.pitch;
2024-06-03 18:26:03 +00:00
}
}
public void PlayBgm(string bgmName)
{
if (_bgmDictionary.TryGetValue(bgmName, out var value))
2024-06-03 18:26:03 +00:00
{
_bgmAudioSource.clip = value;
_bgmAudioSource.Play();
2024-06-03 18:26:03 +00:00
}
else
{
print("Bgm not found: " + bgmName);
}
}
public void StopBgm()
{
_bgmAudioSource.Stop();
2024-06-03 18:26:03 +00:00
}
2024-11-17 15:36:08 +00:00
public void PlaySfx(string sfxName, bool loop = false, bool ignoreTimeScale = false, float? duration = null)
2024-06-03 18:26:03 +00:00
{
if (_sfxDictionary.TryGetValue(sfxName, out var value))
2024-06-03 18:26:03 +00:00
{
if (_sfxPlayTimeDictionary.TryGetValue(sfxName, out var lastPlayTime))
{
if (Time.time - lastPlayTime < _sfxMinInterval)
{
return;
}
}
2024-06-03 18:26:03 +00:00
var availableSfxAudioSource = GetAvailableSfxAudioSource();
availableSfxAudioSource.clip = value;
2024-11-17 15:36:08 +00:00
availableSfxAudioSource.loop = loop;
2024-11-17 15:36:08 +00:00
if (ignoreTimeScale)
{
// Time.timeScale 영향을 받지 않는 효과음 처리
availableSfxAudioSource.pitch = duration.HasValue ? value.length / duration.Value : 1f;
}
else
{
// Time.timeScale 적용
_sfxPitchDictionary[availableSfxAudioSource] = duration.HasValue ? value.length / duration.Value : 1f;
availableSfxAudioSource.pitch = _sfxPitchDictionary[availableSfxAudioSource] * Time.timeScale;
}
availableSfxAudioSource.Play();
_sfxPlayTimeDictionary[sfxName] = Time.time;
2024-06-03 18:26:03 +00:00
}
else
{
print("Sfx not found: " + sfxName);
}
}
public void StopSfx(string sfxName)
{
if (_sfxDictionary.TryGetValue(sfxName, out var clip))
2024-06-03 18:26:03 +00:00
{
foreach (var element in _sfxPitchDictionary.Keys)
2024-06-03 18:26:03 +00:00
{
if (element.clip == clip && element.isPlaying)
{
element.Stop();
}
}
}
else
{
Debug.LogWarning("Sfx not found: " + sfxName);
}
}
public void StopSfxAll()
{
foreach (var element in _sfxPitchDictionary.Keys)
2024-06-03 18:26:03 +00:00
{
if (element.isPlaying)
{
element.Stop();
}
}
}
private AudioSource GetAvailableSfxAudioSource()
{
foreach (var element in _sfxPitchDictionary.Keys)
2024-06-03 18:26:03 +00:00
{
if (!element.isPlaying)
{
return element;
}
}
// 모든 AudioSource가 사용 중이면 첫 번째 AudioSource를 재사용
//return sfxPitchDictionary.Keys.GetEnumerator().Current;
using var enumerator = _sfxPitchDictionary.Keys.GetEnumerator();
2024-06-03 18:26:03 +00:00
enumerator.MoveNext();
return enumerator.Current;
}
2024-10-31 12:17:10 +00:00
/// <summary>
/// 0.0001 ~ 1값
/// </summary>
/// <param name="volume"></param>
2024-06-03 18:26:03 +00:00
public void SetMasterVolume(float volume)
{
2024-10-31 12:17:10 +00:00
var newVolume = Mathf.Log10(volume) * 20f;
_audioMixer.SetFloat("Master", newVolume);
2024-06-03 18:26:03 +00:00
}
public void SetBgmVolume(float volume)
{
2024-10-31 12:17:10 +00:00
var newVolume = Mathf.Log10(volume) * 20f;
_audioMixer.SetFloat("Bgm", newVolume);
2024-06-03 18:26:03 +00:00
}
public void SetSfxVolume(float volume)
{
2024-10-31 12:17:10 +00:00
var newVolume = Mathf.Log10(volume) * 20f;
_audioMixer.SetFloat("Sfx", newVolume);
2024-06-03 18:26:03 +00:00
}
public void SetPitchSfxAll(float pitch)
{
foreach (var element in _sfxPitchDictionary)
2024-06-03 18:26:03 +00:00
{
element.Key.pitch = element.Value * pitch;
}
}
}
}