Skip to content

Instantly share code, notes, and snippets.

@fuzzblob
Last active January 11, 2019 02:50
Show Gist options
  • Save fuzzblob/02be37d273affd511a2e79005ef69063 to your computer and use it in GitHub Desktop.
Save fuzzblob/02be37d273affd511a2e79005ef69063 to your computer and use it in GitHub Desktop.
simple approach to limiting how many AudioSources play a specific clip in Unity
/*
* Usage:
*
* in some other script create an AudioVoices object
*
* public AudioVoices voiceLimiting = new AudioVoices();
*
* then when playing a sound first add the AudioSource to the AudioVoices
* passing the maximum amount of instances and only play it if the source got added:
*
* bool wasAdded = voiecLimiting.AddActiveSource(source, 5);
* if(wasAdded) source.Play();
* else Debug.LogWarning("coud't play " + source.clip + "! voice limit reached!");
*
* Don't forget to keep calling the following every frame to make sure when sounds stop
* that new instances will be allowed to play:
*
* voiceLimiting.CleanSources()
*
*/
using UnityEngine;
using System.Collections.Generic;
public class AudioVoices {
private Dictionary<AudioClip, List<AudioSource>> activeSources;
private List<AudioClip> activeClips;
public AudioVoices() {
activeSources = new Dictionary<AudioClip, List<AudioSource>>();
activeClips = new List<AudioClip>(8);
}
/// <summary>
/// This should be called every now and then? Maybe per frame
/// </summary>
public void CleanSources() {
for(int clip = activeClips.Count - 1; clip >= 0; clip--) {
AudioClip key = activeClips[clip];
List<AudioSource> list;
if (activeSources.TryGetValue(key, out list) == false)
continue;
// iterate over the list and check isf sources have stopped
for (int source = list.Count -1; source >= 0; source--) {
if (list[source].isPlaying)
continue;
// the source is not playing anymore. remove it from the list.
list.RemoveAt(source);
if (list.Count > 0)
continue;
// clean up so less iteration happens when no source attached to a clip anymore
activeSources.Remove(key);
activeClips.RemoveAt(clip);
}
}
}
/// <summary>
/// Add a source to the lookup dictionary if not exceeding maxCount
/// </summary>
/// <param name="source">the source to be added</param>
/// <param name="maxCount">the maximum amount of sources for this audio clip</param>
/// <returns></returns>
public bool AddActiveSource(AudioSource source, int maxCount) {
List<AudioSource> list;
if (activeSources.TryGetValue(source.clip, out list) == false) {
// can't add. no active audiosources allowed atm
if (maxCount < 1)
return false;
// clip had no active sources. make a new list
list = new List<AudioSource>(1);
list.Add(source);
activeSources.Add(source.clip, list);
return true;
}
if (list.Count + 1 > maxCount) {
// TODO: you can instead stop an older sound here if you want?
return false;
}
// add the sound to the list
list.Add(source);
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment