Last active
January 11, 2019 02:50
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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