You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
245 lines
7.5 KiB
245 lines
7.5 KiB
// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus). |
|
// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE) |
|
|
|
using UnityEngine; |
|
using System.Collections.Generic; |
|
|
|
namespace Fungus |
|
{ |
|
/// <summary> |
|
/// Manages audio effects for Dialogs. |
|
/// </summary> |
|
public class WriterAudio : MonoBehaviour, IWriterListener |
|
{ |
|
[Tooltip("Volume level of writing sound effects")] |
|
[Range(0,1)] |
|
[SerializeField] protected float volume = 1f; |
|
|
|
[Tooltip("Loop the audio when in Sound Effect mode. Has no effect in Beeps mode.")] |
|
[SerializeField] protected bool loop = true; |
|
|
|
// If none is specifed then we use any AudioSource on the gameobject, and if that doesn't exist we create one. |
|
[Tooltip("AudioSource to use for playing sound effects. If none is selected then one will be created.")] |
|
[SerializeField] protected AudioSource targetAudioSource; |
|
|
|
public enum AudioMode |
|
{ |
|
Beeps, // Use short beep sound effects |
|
SoundEffect, // Use long looping sound effect |
|
} |
|
|
|
[Tooltip("Type of sound effect to play when writing text")] |
|
[SerializeField] protected AudioMode audioMode = AudioMode.Beeps; |
|
|
|
[Tooltip("List of beeps to randomly select when playing beep sound effects. Will play maximum of one beep per character, with only one beep playing at a time.")] |
|
[SerializeField] protected List<AudioClip> beepSounds = new List<AudioClip>(); |
|
|
|
[Tooltip("Long playing sound effect to play when writing text")] |
|
[SerializeField] protected AudioClip soundEffect; |
|
|
|
[Tooltip("Sound effect to play on user input (e.g. a click)")] |
|
[SerializeField] protected AudioClip inputSound; |
|
|
|
protected float targetVolume = 0f; |
|
|
|
// When true, a beep will be played on every written character glyph |
|
protected bool playBeeps; |
|
|
|
// True when a voiceover clip is playing |
|
protected bool playingVoiceover = false; |
|
|
|
// Time when current beep will have finished playing |
|
protected float nextBeepTime; |
|
|
|
protected virtual void SetAudioMode(AudioMode mode) |
|
{ |
|
audioMode = mode; |
|
} |
|
|
|
protected virtual void Awake() |
|
{ |
|
// Need to do this in Awake rather than Start due to init order issues |
|
if (targetAudioSource == null) |
|
{ |
|
targetAudioSource = GetComponent<AudioSource>(); |
|
if (targetAudioSource == null) |
|
{ |
|
targetAudioSource = gameObject.AddComponent<AudioSource>(); |
|
} |
|
} |
|
|
|
targetAudioSource.volume = 0f; |
|
} |
|
|
|
protected virtual void Play(AudioClip audioClip) |
|
{ |
|
if (targetAudioSource == null || |
|
(audioMode == AudioMode.SoundEffect && soundEffect == null && audioClip == null) || |
|
(audioMode == AudioMode.Beeps && beepSounds.Count == 0)) |
|
{ |
|
return; |
|
} |
|
|
|
playingVoiceover = false; |
|
targetAudioSource.volume = 0f; |
|
targetVolume = volume; |
|
|
|
if (audioClip != null) |
|
{ |
|
// Voice over clip provided |
|
targetAudioSource.clip = audioClip; |
|
targetAudioSource.loop = loop; |
|
targetAudioSource.Play(); |
|
} |
|
else if (audioMode == AudioMode.SoundEffect && |
|
soundEffect != null) |
|
{ |
|
// Use sound effects defined in WriterAudio |
|
targetAudioSource.clip = soundEffect; |
|
targetAudioSource.loop = loop; |
|
targetAudioSource.Play(); |
|
} |
|
else if (audioMode == AudioMode.Beeps) |
|
{ |
|
// Use beeps defined in WriterAudio |
|
targetAudioSource.clip = null; |
|
targetAudioSource.loop = false; |
|
playBeeps = true; |
|
} |
|
} |
|
|
|
protected virtual void Pause() |
|
{ |
|
if (targetAudioSource == null) |
|
{ |
|
return; |
|
} |
|
|
|
// There's an audible click if you call audioSource.Pause() so instead just drop the volume to 0. |
|
targetVolume = 0f; |
|
} |
|
|
|
protected virtual void Stop() |
|
{ |
|
if (targetAudioSource == null) |
|
{ |
|
return; |
|
} |
|
|
|
// There's an audible click if you call audioSource.Stop() so instead we just switch off |
|
// looping and let the audio stop automatically at the end of the clip |
|
targetVolume = 0f; |
|
targetAudioSource.loop = false; |
|
playBeeps = false; |
|
playingVoiceover = false; |
|
} |
|
|
|
protected virtual void Resume() |
|
{ |
|
if (targetAudioSource == null) |
|
{ |
|
return; |
|
} |
|
|
|
targetVolume = volume; |
|
} |
|
|
|
protected virtual void Update() |
|
{ |
|
targetAudioSource.volume = Mathf.MoveTowards(targetAudioSource.volume, targetVolume, Time.deltaTime * 5f); |
|
} |
|
|
|
#region IWriterListener implementation |
|
|
|
public virtual void OnInput() |
|
{ |
|
if (inputSound != null) |
|
{ |
|
// Assumes we're playing a 2D sound |
|
AudioSource.PlayClipAtPoint(inputSound, Vector3.zero); |
|
} |
|
} |
|
|
|
public virtual void OnStart(AudioClip audioClip) |
|
{ |
|
if (playingVoiceover) |
|
{ |
|
return; |
|
} |
|
Play(audioClip); |
|
} |
|
|
|
public virtual void OnPause() |
|
{ |
|
if (playingVoiceover) |
|
{ |
|
return; |
|
} |
|
Pause(); |
|
} |
|
|
|
public virtual void OnResume() |
|
{ |
|
if (playingVoiceover) |
|
{ |
|
return; |
|
} |
|
Resume(); |
|
} |
|
|
|
public virtual void OnEnd(bool stopAudio) |
|
{ |
|
if (stopAudio) |
|
{ |
|
Stop(); |
|
} |
|
} |
|
|
|
public virtual void OnGlyph() |
|
{ |
|
if (playingVoiceover) |
|
{ |
|
return; |
|
} |
|
|
|
if (playBeeps && beepSounds.Count > 0) |
|
{ |
|
if (!targetAudioSource.isPlaying) |
|
{ |
|
if (nextBeepTime < Time.realtimeSinceStartup) |
|
{ |
|
targetAudioSource.clip = beepSounds[Random.Range(0, beepSounds.Count - 1)]; |
|
|
|
if (targetAudioSource.clip != null) |
|
{ |
|
targetAudioSource.loop = false; |
|
targetVolume = volume; |
|
targetAudioSource.Play(); |
|
|
|
float extend = targetAudioSource.clip.length; |
|
nextBeepTime = Time.realtimeSinceStartup + extend; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
public virtual void OnVoiceover(AudioClip voiceOverClip) |
|
{ |
|
if (targetAudioSource == null) |
|
{ |
|
return; |
|
} |
|
|
|
playingVoiceover = true; |
|
|
|
targetAudioSource.volume = volume; |
|
targetVolume = volume; |
|
targetAudioSource.loop = false; |
|
targetAudioSource.clip = voiceOverClip; |
|
targetAudioSource.Play(); |
|
} |
|
|
|
#endregion |
|
} |
|
} |