201 lines
5.5 KiB
C#

using OctoberStudio.Pool;
using System.Collections.Generic;
using UnityEngine;
namespace OctoberStudio.Audio
{
public class AudioManager : MonoBehaviour, IAudioManager
{
public static readonly int BUTTON_CLICK_HASH = "Button Click".GetHashCode();
private static AudioManager instance;
[SerializeField] AudioDatabase database;
[SerializeField] GameObject audioSource;
public AudioDatabase AudioDatabase => database;
private PoolComponent<AudioSource> audioSourcePool;
private List<AudioData> aliveSources = new List<AudioData>();
private Dictionary<int, SoundContainer> sounds;
private AudioSave save;
public float SoundVolume {
get => save.SoundVolume;
set
{
save.SoundVolume = value;
OnSoundVolumeChanged();
}
}
public float MusicVolume
{
get => save.MusicVolume;
set
{
save.MusicVolume = value;
OnMusicVolumeChanged();
}
}
private void Awake()
{
if (instance != null)
{
Destroy(gameObject);
return;
}
instance = this;
DontDestroyOnLoad(gameObject);
audioSourcePool = new PoolComponent<AudioSource>("audio source", audioSource, 2, null, true);
gameObject.AddComponent<AudioListener>();
sounds = new Dictionary<int, SoundContainer>();
for(int i = 0; i < database.Sounds.Count; i++)
{
var sound = database.Sounds[i];
var hash = sound.Name.GetHashCode();
if (sounds.ContainsKey(hash))
{
Debug.LogError($"Audio clip with the name {sound.Name} has already been added. You should rename one of the entries with this name.");
} else
{
sound.Init();
sounds.Add(hash, sound);
}
}
GameController.RegisterAudioManager(this);
}
private void Start()
{
save = GameController.SaveManager.GetSave<AudioSave>("Audio");
}
public AudioSource PlaySound(AudioClip clip, float volume = 1, float pitch = 1)
{
var source = audioSourcePool.GetEntity();
source.clip = clip;
source.loop = false;
source.pitch = pitch;
source.volume = volume * save.SoundVolume;
var data = new AudioData() { source = source, volume = volume };
aliveSources.Add(data);
source.Play();
return source;
}
public AudioSource PlaySound(int hash, float volume = 1, float pitch = 1)
{
if (sounds.ContainsKey(hash))
{
return sounds[hash].Play(false, volume, pitch);
}
Debug.LogWarning($"There are no sound with hash {hash} in the AudioDatabase");
return null;
}
public AudioSource PlaySound(AudioClipData clipData, float volume = 1, float pitch = 1)
{
var source = audioSourcePool.GetEntity();
source.clip = clipData.AudioClip;
source.loop = false;
source.pitch = clipData.Pitch * pitch;
source.volume = clipData.Volume * save.SoundVolume * volume;
var data = new AudioData() { source = source, volume = clipData.Volume };
aliveSources.Add(data);
source.Play();
return source;
}
public AudioSource PlayMusic(AudioClipData clipData)
{
var source = audioSourcePool.GetEntity();
source.clip = clipData.AudioClip;
source.loop = true;
source.pitch = clipData.Pitch;
source.volume = clipData.Volume * save.MusicVolume;
var data = new AudioData() { source = source, volume = clipData.Volume };
aliveSources.Add(data);
source.Play();
return source;
}
public AudioSource PlayMusic(int hash)
{
if (sounds.ContainsKey(hash))
{
return sounds[hash].Play(true);
}
Debug.LogWarning($"There are no sound with hash {hash} in the AudioDatabase");
return null;
}
private void OnSoundVolumeChanged()
{
foreach(var source in aliveSources)
{
if (!source.source.loop)
{
source.source.volume = source.volume * save.SoundVolume;
}
}
}
private void OnMusicVolumeChanged()
{
foreach (var source in aliveSources)
{
if (source.source.loop)
{
source.source.volume = source.volume * save.MusicVolume;
}
}
}
private void Update()
{
for(int i = 0; i < aliveSources.Count; i++)
{
if (!aliveSources[i].source.isPlaying && !aliveSources[i].source.loop)
{
aliveSources[i].source.gameObject.SetActive(false);
aliveSources.RemoveAt(i);
i--;
}
}
}
public class AudioData
{
public AudioSource source;
public float volume;
}
}
}