using UnityEngine;
///
/// Audio source that fades between clips instead of playing them immediately.
///
[RequireComponent(typeof(AudioSource))]
public class FadingAudioSource : MonoBehaviour {
#region Fields
///
/// Volume to end the previous clip at.
///
public float FadeOutThreshold = 0.05f;
///
/// Volume change per second when fading.
///
public float FadeSpeed = 1f;
///
/// Actual audio source.
///
private AudioSource audioSource;
///
/// Whether the audio source is currently fading, in or out.
///
private FadeState fadeState = FadeState.None;
///
/// Next clip to fade to.
///
private AudioClip nextClip;
///
/// Whether to loop the next clip.
///
private bool nextClipLoop;
///
/// Target volume to fade the next clip to.
///
private float nextClipVolume;
#endregion
#region Enums
public enum FadeState {
None,
FadingOut,
FadingIn
}
#endregion
#region Public Properties
///
/// Current clip of the audio source.
///
public AudioClip Clip {
get {
return this.audioSource.clip;
}
}
///
/// Whether the audio source is currently playing a clip.
///
public bool IsPlaying {
get {
return this.audioSource.isPlaying;
}
}
///
/// Whether the audio source is looping the current clip.
///
public bool Loop {
get {
return this.audioSource.loop;
}
}
///
/// Current volume of the audio source.
///
public float Volume {
get {
return this.audioSource.volume;
}
}
#endregion
#region Public Methods and Operators
///
/// If the audio source is enabled and playing, fades out the current clip and fades in the specified one, after.
/// If the audio source is enabled and not playing, fades in the specified clip immediately.
/// If the audio source is not enalbed, fades in the specified clip as soon as it gets enabled.
///
/// Clip to fade in.
/// Volume to fade to.
/// Whether to loop the new clip, or not.
public void Fade(AudioClip clip, float volume, bool loop) {
if (clip == null || clip == this.audioSource.clip) {
return;
}
this.nextClip = clip;
this.nextClipVolume = volume;
this.nextClipLoop = loop;
if (this.audioSource.enabled) {
if (this.IsPlaying) {
this.fadeState = FadeState.FadingOut;
} else {
this.FadeToNextClip();
}
} else {
this.FadeToNextClip();
}
}
///
/// Continues fading in the current audio clip.
///
public void Play() {
this.fadeState = FadeState.FadingIn;
this.audioSource.Play();
}
///
/// Stop playing the current audio clip immediately.
///
public void Stop() {
this.audioSource.Stop();
this.fadeState = FadeState.None;
}
#endregion
#region Methods
private void Awake() {
this.audioSource = GetComponent();
this.audioSource.volume = 0f;
}
private void FadeToNextClip() {
this.audioSource.clip = this.nextClip;
this.audioSource.loop = this.nextClipLoop;
this.fadeState = FadeState.FadingIn;
if (this.audioSource.enabled) {
this.audioSource.Play();
}
}
private void OnDisable() {
this.audioSource.enabled = false;
this.Stop();
}
private void OnEnable() {
this.audioSource.enabled = true;
this.Play();
}
private void Update() {
if (!this.audioSource.enabled) {
return;
}
if (this.fadeState == FadeState.FadingOut) {
if (this.audioSource.volume > this.FadeOutThreshold) {
// Fade out current clip.
this.audioSource.volume -= this.FadeSpeed * Time.deltaTime;
} else {
// Start fading in next clip.
this.FadeToNextClip();
}
} else if (this.fadeState == FadeState.FadingIn) {
if (this.audioSource.volume < this.nextClipVolume) {
// Fade in next clip.
this.audioSource.volume += this.FadeSpeed * Time.deltaTime;
} else {
// Stop fading in.
this.fadeState = FadeState.None;
}
}
}
#endregion
}