using System.Collections; using System.Collections.Generic; using UnityEngine; namespace Management { /// /// 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. /// [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 _clipsInProgress; /// /// Plpays the given audio clip through the audio driver /// /// The sound to play /// The normalized volume it will play at 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(); } } }