182 lines
5.6 KiB
C#
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;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|