334 lines
16 KiB
C#
334 lines
16 KiB
C#
|
using System.Collections;
|
|||
|
using System.Collections.Generic;
|
|||
|
using UnityEngine;
|
|||
|
using System.Threading.Tasks;
|
|||
|
using MoreMountains.Tools;
|
|||
|
using UnityEngine.Audio;
|
|||
|
|
|||
|
namespace MoreMountains.Feedbacks
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// This feedback will let you play a sound via the MMSoundManager. You will need a game object in your scene with a MMSoundManager object on it for this to work.
|
|||
|
/// </summary>
|
|||
|
[ExecuteAlways]
|
|||
|
[AddComponentMenu("")]
|
|||
|
[FeedbackPath("Audio/MMSoundManager Sound")]
|
|||
|
[FeedbackHelp("This feedback will let you play a sound via the MMSoundManager. You will need a game object in your scene with a MMSoundManager object on it for this to work.")]
|
|||
|
public class MMFeedbackMMSoundManagerSound : MMFeedback
|
|||
|
{
|
|||
|
/// sets the inspector color for this feedback
|
|||
|
#if UNITY_EDITOR
|
|||
|
public override Color FeedbackColor { get { return MMFeedbacksInspectorColors.SoundsColor; } }
|
|||
|
#endif
|
|||
|
|
|||
|
/// the duration of this feedback is the duration of the clip being played
|
|||
|
public override float FeedbackDuration { get { return GetDuration(); } }
|
|||
|
|
|||
|
[Header("Sound")]
|
|||
|
/// the sound clip to play
|
|||
|
[Tooltip("the sound clip to play")]
|
|||
|
public AudioClip Sfx;
|
|||
|
|
|||
|
[Header("Random Sound")]
|
|||
|
/// an array to pick a random sfx from
|
|||
|
[Tooltip("an array to pick a random sfx from")]
|
|||
|
public AudioClip[] RandomSfx;
|
|||
|
|
|||
|
[Header("Test")]
|
|||
|
[MMFInspectorButton("TestPlaySound")]
|
|||
|
public bool TestButton;
|
|||
|
[MMFInspectorButton("TestStopSound")]
|
|||
|
public bool TestStopButton;
|
|||
|
|
|||
|
[Header("Volume")]
|
|||
|
/// the minimum volume to play the sound at
|
|||
|
[Tooltip("the minimum volume to play the sound at")]
|
|||
|
public float MinVolume = 1f;
|
|||
|
/// the maximum volume to play the sound at
|
|||
|
[Tooltip("the maximum volume to play the sound at")]
|
|||
|
public float MaxVolume = 1f;
|
|||
|
|
|||
|
[Header("Pitch")]
|
|||
|
/// the minimum pitch to play the sound at
|
|||
|
[Tooltip("the minimum pitch to play the sound at")]
|
|||
|
public float MinPitch = 1f;
|
|||
|
/// the maximum pitch to play the sound at
|
|||
|
[Tooltip("the maximum pitch to play the sound at")]
|
|||
|
public float MaxPitch = 1f;
|
|||
|
|
|||
|
[Header("SoundManager Options")]
|
|||
|
/// the track on which to play the sound. Pick the one that matches the nature of your sound
|
|||
|
[Tooltip("the track on which to play the sound. Pick the one that matches the nature of your sound")]
|
|||
|
public MMSoundManager.MMSoundManagerTracks MmSoundManagerTrack = MMSoundManager.MMSoundManagerTracks.Sfx;
|
|||
|
/// the ID of the sound. This is useful if you plan on using sound control feedbacks on it afterwards.
|
|||
|
[Tooltip("the ID of the sound. This is useful if you plan on using sound control feedbacks on it afterwards.")]
|
|||
|
public int ID = 0;
|
|||
|
/// the AudioGroup on which to play the sound. If you're already targeting a preset track, you can leave it blank, otherwise the group you specify here will override it.
|
|||
|
[Tooltip("the AudioGroup on which to play the sound. If you're already targeting a preset track, you can leave it blank, otherwise the group you specify here will override it.")]
|
|||
|
public AudioMixerGroup AudioGroup = null;
|
|||
|
/// if (for some reason) you've already got an audiosource and wouldn't like to use the built-in pool system, you can specify it here
|
|||
|
[Tooltip("if (for some reason) you've already got an audiosource and wouldn't like to use the built-in pool system, you can specify it here")]
|
|||
|
public AudioSource RecycleAudioSource = null;
|
|||
|
/// whether or not this sound should loop
|
|||
|
[Tooltip("whether or not this sound should loop")]
|
|||
|
public bool Loop = false;
|
|||
|
/// whether or not this sound should continue playing when transitioning to another scene
|
|||
|
[Tooltip("whether or not this sound should continue playing when transitioning to another scene")]
|
|||
|
public bool Persistent = false;
|
|||
|
|
|||
|
[Header("Fade")]
|
|||
|
/// whether or not to fade this sound in when playing it
|
|||
|
[Tooltip("whether or not to fade this sound in when playing it")]
|
|||
|
public bool Fade = false;
|
|||
|
/// if fading, the volume at which to start the fade
|
|||
|
[Tooltip("if fading, the volume at which to start the fade")]
|
|||
|
[MMCondition("Fade", true)]
|
|||
|
public float FadeInitialVolume = 0f;
|
|||
|
/// if fading, the duration of the fade, in seconds
|
|||
|
[Tooltip("if fading, the duration of the fade, in seconds")]
|
|||
|
[MMCondition("Fade", true)]
|
|||
|
public float FadeDuration = 1f;
|
|||
|
/// if fading, the tween over which to fade the sound
|
|||
|
[Tooltip("if fading, the tween over which to fade the sound ")]
|
|||
|
[MMCondition("Fade", true)]
|
|||
|
public MMTweenType FadeTween = new MMTweenType(MMTween.MMTweenCurve.EaseInOutQuartic);
|
|||
|
|
|||
|
[Header("Solo")]
|
|||
|
/// whether or not this sound should play in solo mode over its destination track. If yes, all other sounds on that track will be muted when this sound starts playing
|
|||
|
[Tooltip("whether or not this sound should play in solo mode over its destination track. If yes, all other sounds on that track will be muted when this sound starts playing")]
|
|||
|
public bool SoloSingleTrack = false;
|
|||
|
/// whether or not this sound should play in solo mode over all other tracks. If yes, all other tracks will be muted when this sound starts playing
|
|||
|
[Tooltip("whether or not this sound should play in solo mode over all other tracks. If yes, all other tracks will be muted when this sound starts playing")]
|
|||
|
public bool SoloAllTracks = false;
|
|||
|
/// if in any of the above solo modes, AutoUnSoloOnEnd will unmute the track(s) automatically once that sound stops playing
|
|||
|
[Tooltip("if in any of the above solo modes, AutoUnSoloOnEnd will unmute the track(s) automatically once that sound stops playing")]
|
|||
|
public bool AutoUnSoloOnEnd = false;
|
|||
|
|
|||
|
[Header("Spatial Settings")]
|
|||
|
/// Pans a playing sound in a stereo way (left or right). This only applies to sounds that are Mono or Stereo.
|
|||
|
[Tooltip("Pans a playing sound in a stereo way (left or right). This only applies to sounds that are Mono or Stereo.")]
|
|||
|
public float PanStereo;
|
|||
|
/// Sets how much this AudioSource is affected by 3D spatialisation calculations (attenuation, doppler etc). 0.0 makes the sound full 2D, 1.0 makes it full 3D.
|
|||
|
[Tooltip("Sets how much this AudioSource is affected by 3D spatialisation calculations (attenuation, doppler etc). 0.0 makes the sound full 2D, 1.0 makes it full 3D.")]
|
|||
|
public float SpatialBlend;
|
|||
|
|
|||
|
[Header("Effects")]
|
|||
|
/// Bypass effects (Applied from filter components or global listener filters).
|
|||
|
[Tooltip("Bypass effects (Applied from filter components or global listener filters).")]
|
|||
|
public bool BypassEffects;
|
|||
|
/// When set global effects on the AudioListener will not be applied to the audio signal generated by the AudioSource. Does not apply if the AudioSource is playing into a mixer group.
|
|||
|
[Tooltip("When set global effects on the AudioListener will not be applied to the audio signal generated by the AudioSource. Does not apply if the AudioSource is playing into a mixer group.")]
|
|||
|
public bool BypassListenerEffects;
|
|||
|
/// When set doesn't route the signal from an AudioSource into the global reverb associated with reverb zones.
|
|||
|
[Tooltip("When set doesn't route the signal from an AudioSource into the global reverb associated with reverb zones.")]
|
|||
|
public bool BypassReverbZones;
|
|||
|
/// Sets the priority of the AudioSource.
|
|||
|
[Tooltip("Sets the priority of the AudioSource.")]
|
|||
|
public int Priority;
|
|||
|
/// The amount by which the signal from the AudioSource will be mixed into the global reverb associated with the Reverb Zones.
|
|||
|
[Tooltip("The amount by which the signal from the AudioSource will be mixed into the global reverb associated with the Reverb Zones.")]
|
|||
|
public float ReverbZoneMix;
|
|||
|
/// Sets the Doppler scale for this AudioSource.
|
|||
|
[Tooltip("Sets the Doppler scale for this AudioSource.")]
|
|||
|
public float DopplerLevel;
|
|||
|
/// Sets the spread angle (in degrees) of a 3d stereo or multichannel sound in speaker space.
|
|||
|
[Tooltip("Sets the spread angle (in degrees) of a 3d stereo or multichannel sound in speaker space.")]
|
|||
|
public int Spread;
|
|||
|
/// Sets/Gets how the AudioSource attenuates over distance.
|
|||
|
[Tooltip("Sets/Gets how the AudioSource attenuates over distance.")]
|
|||
|
public AudioRolloffMode RolloffMode;
|
|||
|
/// Within the Min distance the AudioSource will cease to grow louder in volume.
|
|||
|
[Tooltip("Within the Min distance the AudioSource will cease to grow louder in volume.")]
|
|||
|
public float MinDistance;
|
|||
|
/// (Logarithmic rolloff) MaxDistance is the distance a sound stops attenuating at.
|
|||
|
[Tooltip("(Logarithmic rolloff) MaxDistance is the distance a sound stops attenuating at.")]
|
|||
|
public float MaxDistance;
|
|||
|
|
|||
|
protected AudioClip _randomClip;
|
|||
|
protected AudioSource _editorAudioSource;
|
|||
|
protected MMSoundManagerPlayOptions _options;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Plays either a random sound or the specified sfx
|
|||
|
/// </summary>
|
|||
|
/// <param name="position"></param>
|
|||
|
/// <param name="feedbacksIntensity"></param>
|
|||
|
protected override void CustomPlayFeedback(Vector3 position, float feedbacksIntensity = 1.0f)
|
|||
|
{
|
|||
|
float intensityMultiplier = Timing.ConstantIntensity ? 1f : feedbacksIntensity;
|
|||
|
if (Active)
|
|||
|
{
|
|||
|
if (Sfx != null)
|
|||
|
{
|
|||
|
PlaySound(Sfx, position, intensityMultiplier);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (RandomSfx.Length > 0)
|
|||
|
{
|
|||
|
_randomClip = RandomSfx[Random.Range(0, RandomSfx.Length)];
|
|||
|
|
|||
|
if (_randomClip != null)
|
|||
|
{
|
|||
|
PlaySound(_randomClip, position, intensityMultiplier);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Triggers a play sound event
|
|||
|
/// </summary>
|
|||
|
/// <param name="sfx"></param>
|
|||
|
/// <param name="position"></param>
|
|||
|
/// <param name="intensity"></param>
|
|||
|
protected virtual void PlaySound(AudioClip sfx, Vector3 position, float intensity)
|
|||
|
{
|
|||
|
float volume = Random.Range(MinVolume, MaxVolume);
|
|||
|
|
|||
|
if (!Timing.ConstantIntensity)
|
|||
|
{
|
|||
|
volume = volume * intensity;
|
|||
|
}
|
|||
|
|
|||
|
float pitch = Random.Range(MinPitch, MaxPitch);
|
|||
|
|
|||
|
int timeSamples = NormalPlayDirection ? 0 : sfx.samples - 1;
|
|||
|
|
|||
|
if (!NormalPlayDirection)
|
|||
|
{
|
|||
|
pitch = -pitch;
|
|||
|
}
|
|||
|
|
|||
|
_options.MmSoundManagerTrack = MmSoundManagerTrack;
|
|||
|
_options.Location = position;
|
|||
|
_options.Loop = Loop;
|
|||
|
_options.Volume = volume;
|
|||
|
_options.ID = ID;
|
|||
|
_options.Fade = Fade;
|
|||
|
_options.FadeInitialVolume = FadeInitialVolume;
|
|||
|
_options.FadeDuration = FadeDuration;
|
|||
|
_options.FadeTween = FadeTween;
|
|||
|
_options.Persistent = Persistent;
|
|||
|
_options.RecycleAudioSource = RecycleAudioSource;
|
|||
|
_options.AudioGroup = AudioGroup;
|
|||
|
_options.Pitch = pitch;
|
|||
|
_options.PanStereo = PanStereo;
|
|||
|
_options.SpatialBlend = SpatialBlend;
|
|||
|
_options.SoloSingleTrack = SoloSingleTrack;
|
|||
|
_options.SoloAllTracks = SoloAllTracks;
|
|||
|
_options.AutoUnSoloOnEnd = AutoUnSoloOnEnd;
|
|||
|
_options.BypassEffects = BypassEffects;
|
|||
|
_options.BypassListenerEffects = BypassListenerEffects;
|
|||
|
_options.BypassReverbZones = BypassReverbZones;
|
|||
|
_options.Priority = Priority;
|
|||
|
_options.ReverbZoneMix = ReverbZoneMix;
|
|||
|
_options.DopplerLevel = DopplerLevel;
|
|||
|
_options.Spread = Spread;
|
|||
|
_options.RolloffMode = RolloffMode;
|
|||
|
_options.MinDistance = MinDistance;
|
|||
|
_options.MaxDistance = MaxDistance;
|
|||
|
|
|||
|
MMSoundManagerSoundPlayEvent.Trigger(sfx, _options);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Returns the duration of the sound, or of the longest of the random sounds
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
protected virtual float GetDuration()
|
|||
|
{
|
|||
|
if (Sfx != null)
|
|||
|
{
|
|||
|
return Sfx.length;
|
|||
|
}
|
|||
|
|
|||
|
float longest = 0f;
|
|||
|
if ((RandomSfx != null) && (RandomSfx.Length > 0))
|
|||
|
{
|
|||
|
foreach (AudioClip clip in RandomSfx)
|
|||
|
{
|
|||
|
if ((clip != null) && (clip.length > longest))
|
|||
|
{
|
|||
|
longest = clip.length;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return longest;
|
|||
|
}
|
|||
|
|
|||
|
return 0f;
|
|||
|
}
|
|||
|
|
|||
|
#region TestMethods
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// A test method that creates an audiosource, plays it, and destroys itself after play
|
|||
|
/// </summary>
|
|||
|
protected virtual async void TestPlaySound()
|
|||
|
{
|
|||
|
AudioClip tmpAudioClip = null;
|
|||
|
|
|||
|
if (Sfx != null)
|
|||
|
{
|
|||
|
tmpAudioClip = Sfx;
|
|||
|
}
|
|||
|
|
|||
|
if (RandomSfx.Length > 0)
|
|||
|
{
|
|||
|
tmpAudioClip = RandomSfx[Random.Range(0, RandomSfx.Length)];
|
|||
|
}
|
|||
|
|
|||
|
if (tmpAudioClip == null)
|
|||
|
{
|
|||
|
Debug.LogError(Label + " on " + this.gameObject.name + " can't play in editor mode, you haven't set its Sfx.");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
float volume = Random.Range(MinVolume, MaxVolume);
|
|||
|
float pitch = Random.Range(MinPitch, MaxPitch);
|
|||
|
GameObject temporaryAudioHost = new GameObject("EditorTestAS_WillAutoDestroy");
|
|||
|
temporaryAudioHost.transform.position = this.transform.position;
|
|||
|
_editorAudioSource = temporaryAudioHost.AddComponent<AudioSource>() as AudioSource;
|
|||
|
PlayAudioSource(_editorAudioSource, tmpAudioClip, volume, pitch, 0);
|
|||
|
float length = 1000 * tmpAudioClip.length;
|
|||
|
await Task.Delay((int)length);
|
|||
|
DestroyImmediate(temporaryAudioHost);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// A test method that stops the test sound
|
|||
|
/// </summary>
|
|||
|
protected virtual void TestStopSound()
|
|||
|
{
|
|||
|
if (_editorAudioSource != null)
|
|||
|
{
|
|||
|
_editorAudioSource.Stop();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Plays the audio source with the specified volume and pitch
|
|||
|
/// </summary>
|
|||
|
/// <param name="audioSource"></param>
|
|||
|
/// <param name="sfx"></param>
|
|||
|
/// <param name="volume"></param>
|
|||
|
/// <param name="pitch"></param>
|
|||
|
protected virtual void PlayAudioSource(AudioSource audioSource, AudioClip sfx, float volume, float pitch, int timeSamples)
|
|||
|
{
|
|||
|
// we set that audio source clip to the one in paramaters
|
|||
|
audioSource.clip = sfx;
|
|||
|
audioSource.timeSamples = timeSamples;
|
|||
|
// we set the audio source volume to the one in parameters
|
|||
|
audioSource.volume = volume;
|
|||
|
audioSource.pitch = pitch;
|
|||
|
// we set our loop setting
|
|||
|
audioSource.loop = false;
|
|||
|
// we start playing the sound
|
|||
|
audioSource.Play();
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
}
|
|||
|
}
|