using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Audio; using UnityEngine.SceneManagement; namespace MoreMountains.Tools { /// /// This class manages an object pool of audiosources /// [Serializable] public class MMSoundManagerAudioPool { protected List _pool; /// /// Fills the pool with ready-to-use audiosources /// /// /// public virtual void FillAudioSourcePool(int poolSize, Transform parent) { if (_pool == null) { _pool = new List(); } if ((poolSize <= 0) || (_pool.Count >= poolSize)) { return; } foreach (AudioSource source in _pool) { UnityEngine.Object.Destroy(source.gameObject); } for (int i = 0; i < poolSize; i++) { GameObject temporaryAudioHost = new GameObject("MMAudioSourcePool_"+i); SceneManager.MoveGameObjectToScene(temporaryAudioHost.gameObject, parent.gameObject.scene); AudioSource tempSource = temporaryAudioHost.AddComponent(); MMFollowTarget followTarget = temporaryAudioHost.AddComponent(); followTarget.enabled = false; followTarget.DisableSelfOnSetActiveFalse = true; temporaryAudioHost.transform.SetParent(parent); temporaryAudioHost.SetActive(false); _pool.Add(tempSource); } } /// /// Disables an audio source after it's done playing /// /// /// /// public virtual IEnumerator AutoDisableAudioSource(float duration, AudioSource source, AudioClip clip, bool doNotAutoRecycleIfNotDonePlaying, float playbackTime, float playbackDuration) { float initialWait = (playbackDuration > 0) ? playbackDuration : duration; yield return MMCoroutine.WaitFor(initialWait); if (source.clip != clip) { yield break; } if (doNotAutoRecycleIfNotDonePlaying) { float maxTime = (playbackDuration > 0) ? playbackTime + playbackDuration : source.clip.length; while (source.time < maxTime) { yield return null; } } source.gameObject.SetActive(false); } /// /// Pulls an available audio source from the pool /// /// /// /// public virtual AudioSource GetAvailableAudioSource(bool poolCanExpand, Transform parent) { foreach (AudioSource source in _pool) { if (!source.gameObject.activeInHierarchy) { source.gameObject.SetActive(true); return source; } } if (poolCanExpand) { GameObject temporaryAudioHost = new GameObject("MMAudioSourcePool_"+_pool.Count); SceneManager.MoveGameObjectToScene(temporaryAudioHost.gameObject, parent.gameObject.scene); AudioSource tempSource = temporaryAudioHost.AddComponent(); temporaryAudioHost.transform.SetParent(parent); temporaryAudioHost.SetActive(true); _pool.Add(tempSource); return tempSource; } return null; } /// /// Stops an audiosource and returns it to the pool /// /// /// public virtual bool FreeSound(AudioSource sourceToStop) { foreach (AudioSource source in _pool) { if (source == sourceToStop) { source.Stop(); source.gameObject.SetActive(false); return true; } } return false; } } }