66 lines
2.2 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Management
{
/// <summary>
/// Single drive to play all SFX in game. Contains a limiter that limits amount of times
/// any one clip will play to prevent volume runaways and other sound wave based oddities.
/// </summary>
[RequireComponent(typeof(AudioSource))]
public class SFX : MonoBehaviour
{
// The maximum number any individual clip can be played.
[SerializeField] private int maxActiveClips;
// singleton pattern
private static SFX _instance;
// audio driver
private AudioSource _audioSource;
// Playing clip registry. Used as data source to limit amount of times a clip will play simultaneously
private Dictionary<AudioClip, int> _clipsInProgress;
/// <summary>
/// Plpays the given audio clip through the audio driver
/// </summary>
/// <param name="clip">The sound to play</param>
/// <param name="volume">The normalized volume it will play at</param>
public void PlayOneShot(AudioClip clip, float volume = 1f)
{
if (clip == null) return;
if (!_clipsInProgress.TryAdd(clip, 1))
{
if (_clipsInProgress[clip] >= maxActiveClips) return;
_clipsInProgress[clip]++;
}
_audioSource.PlayOneShot(clip, volume);
StartCoroutine(ClearClip(clip));
}
// Coroutine to clear registry once sound is finished.
private IEnumerator ClearClip(AudioClip clip)
{
yield return new WaitForSeconds(clip.length);
_clipsInProgress[clip]--;
if (_clipsInProgress[clip] <= 0) _clipsInProgress.Remove(clip);
}
private void Awake()
{
if (_instance != null && _instance != this)
{
Destroy(gameObject);
return;
}
_instance = this;
DontDestroyOnLoad(gameObject);
_audioSource = GetComponent<AudioSource>();
}
}
}