CapersProject/Assets/02.Scripts/Audio/AudioManager.cs
2024-06-04 03:26:03 +09:00

182 lines
5.6 KiB
C#

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 = 16;
[Title("오디오 믹서")]
[SerializeField] private AudioMixer audioMixer;
[SerializeField] private AudioMixerGroup masterMixerGroup;
[SerializeField] private AudioMixerGroup bgmMixerGroup;
[SerializeField] private AudioMixerGroup sfxMixerGroup;
private Dictionary<string, AudioClip> bgmDictionary;
private Dictionary<string, AudioClip> sfxDictionary;
private AudioSource bgmAudioSource;
private Dictionary<AudioSource, float> sfxPitchDictionary;
protected override void OnAwake()
{
InitDictionary();
InitComponent();
SceneManager.sceneLoaded += OnSceneLoaded;
}
private void OnDestroy()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
StopBgm();
StopSfxAll();
}
private void InitDictionary()
{
bgmDictionary = new Dictionary<string, AudioClip>(bgmDataSo.BgmDataList.Count);
foreach (var element in bgmDataSo.BgmDataList)
{
bgmDictionary.Add(element.BgmName, element.Clip);
}
sfxDictionary = new Dictionary<string, AudioClip>(sfxDataSo.SfxDataList.Count);
foreach (var element in sfxDataSo.SfxDataList)
{
sfxDictionary.Add(element.SfxName, element.Clip);
}
}
private void InitComponent()
{
bgmAudioSource = gameObject.AddComponent<AudioSource>();
bgmAudioSource.outputAudioMixerGroup = bgmMixerGroup;
bgmAudioSource.loop = true;
sfxPitchDictionary = new Dictionary<AudioSource, float>(sfxChannelCount);
for (var i = 0; i < sfxChannelCount; i++)
{
var sfxAudioSource = gameObject.AddComponent<AudioSource>();
sfxAudioSource.outputAudioMixerGroup = sfxMixerGroup;
sfxAudioSource.loop = false;
sfxPitchDictionary[sfxAudioSource] = sfxAudioSource.pitch;
}
}
public void PlayBgm(string bgmName)
{
if (bgmDictionary.TryGetValue(bgmName, out var value))
{
bgmAudioSource.clip = value;
bgmAudioSource.Play();
}
else
{
print("Bgm not found: " + bgmName);
}
}
public void StopBgm()
{
bgmAudioSource.Stop();
}
public void PlaySfx(string sfxName, float? duration = null)
{
if (sfxDictionary.TryGetValue(sfxName, out var value))
{
var availableSfxAudioSource = GetAvailableSfxAudioSource();
availableSfxAudioSource.clip = value;
sfxPitchDictionary[availableSfxAudioSource] = duration.HasValue ? value.length / duration.Value : 1f;
availableSfxAudioSource.pitch = sfxPitchDictionary[availableSfxAudioSource] * Time.timeScale;
availableSfxAudioSource.Play();
}
else
{
print("Sfx not found: " + sfxName);
}
}
public void StopSfx(string sfxName)
{
if (sfxDictionary.TryGetValue(sfxName, out var clip))
{
foreach (var element in sfxPitchDictionary.Keys)
{
if (element.clip == clip && element.isPlaying)
{
element.Stop();
}
}
}
else
{
Debug.LogWarning("Sfx not found: " + sfxName);
}
}
public void StopSfxAll()
{
foreach (var element in sfxPitchDictionary.Keys)
{
if (element.isPlaying)
{
element.Stop();
}
}
}
private AudioSource GetAvailableSfxAudioSource()
{
foreach (var element in sfxPitchDictionary.Keys)
{
if (!element.isPlaying)
{
return element;
}
}
// 모든 AudioSource가 사용 중이면 첫 번째 AudioSource를 재사용
//return sfxPitchDictionary.Keys.GetEnumerator().Current;
using var enumerator = sfxPitchDictionary.Keys.GetEnumerator();
enumerator.MoveNext();
return enumerator.Current;
}
public void SetMasterVolume(float volume)
{
audioMixer.SetFloat("Master", volume);
}
public void SetBgmVolume(float volume)
{
audioMixer.SetFloat("Bgm", volume);
}
public void SetSfxVolume(float volume)
{
audioMixer.SetFloat("Sfx", volume);
}
public void SetPitchSfxAll(float pitch)
{
foreach (var element in sfxPitchDictionary)
{
element.Key.pitch = element.Value * pitch;
}
}
}
}