178 lines
5.0 KiB
C#
178 lines
5.0 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Audio;
|
|
|
|
namespace Prototype
|
|
{
|
|
[CreateAssetMenu(menuName = "Prototype/Sound Effect")]
|
|
public class SoundEffect : ScriptableObject
|
|
{
|
|
[SerializeField] SoundEffectDistanceRange distanceRange;
|
|
[SerializeField] Vector2 volumeMultiplier = new(1, 1);
|
|
[SerializeField] Vector2 pitch = new(.95f, 1.05f);
|
|
|
|
[Header("Additional Settings")]
|
|
public AudioMixerGroup audioMixerGroup;
|
|
public float volumeMultiplierFactor = 1;
|
|
[SerializeField] bool loop;
|
|
[SerializeField] Vector2 fade = new();
|
|
|
|
|
|
[Header("Additional Settings")]
|
|
[SerializeField, Range(0, 1)] float defaultVolume = .8f;
|
|
[SerializeField, Range(-1, 1)] float additionalGain = 0;
|
|
[SerializeField] float maxPlayInterval = .1f;
|
|
|
|
[Header("Clips")]
|
|
[SerializeField] List<AudioClip> clips;
|
|
|
|
public int ClipCount => clips.Count;
|
|
|
|
float lastPlayTime;
|
|
|
|
public SoundEffectOptions ToOptions() => new()
|
|
{
|
|
audioMixerGroup = audioMixerGroup,
|
|
volumeMultiplier = Random.Range(volumeMultiplier.x, volumeMultiplier.y) * volumeMultiplierFactor,
|
|
pitch = Random.Range(pitch.x, pitch.y),
|
|
loop = loop,
|
|
distanceRange = distanceRange ? distanceRange.range : null,
|
|
fade = fade
|
|
};
|
|
|
|
#if UNITY_EDITOR
|
|
public void ApplyVolumeMultiplierFactor()
|
|
{
|
|
volumeMultiplier *= volumeMultiplierFactor;
|
|
volumeMultiplierFactor = 1;
|
|
}
|
|
|
|
void OnEnable()
|
|
{
|
|
Initialize();
|
|
UnityEditor.EditorApplication.playModeStateChanged -= PlayModeStateChanged;
|
|
UnityEditor.EditorApplication.playModeStateChanged += PlayModeStateChanged;
|
|
}
|
|
|
|
void PlayModeStateChanged(UnityEditor.PlayModeStateChange change)
|
|
{
|
|
if (change == UnityEditor.PlayModeStateChange.EnteredEditMode)
|
|
{
|
|
Initialize();
|
|
return;
|
|
}
|
|
|
|
if (change == UnityEditor.PlayModeStateChange.ExitingEditMode)
|
|
{
|
|
Initialize();
|
|
return;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void Initialize()
|
|
{
|
|
lastPlayTime = -1;
|
|
}
|
|
|
|
public AudioClip GetClip(int index)
|
|
{
|
|
return clips[index];
|
|
}
|
|
|
|
public SoundEffectInstance Play()
|
|
{
|
|
return PlayInternal(Vector3.zero, 0);
|
|
}
|
|
|
|
public SoundEffectInstance Play(Vector3 position)
|
|
{
|
|
return PlayInternal(position, 0);
|
|
}
|
|
|
|
public SoundEffectInstance Play(Transform transform)
|
|
{
|
|
return PlayInternal(transform.position, 0);
|
|
}
|
|
|
|
public SoundEffectInstance Play(Vector3 position, float delay)
|
|
{
|
|
return PlayInternal(position, delay);
|
|
}
|
|
|
|
public SoundEffectInstance Play(Transform transform, float delay)
|
|
{
|
|
return PlayInternal(transform.position, delay);
|
|
}
|
|
|
|
public SoundEffectInstance PlayFirstClip()
|
|
{
|
|
return PlayInternal(Vector3.zero, 0, true);
|
|
}
|
|
|
|
public SoundEffectInstance PlayFirstClip(bool destroyOnLoad)
|
|
{
|
|
return PlayInternal(Vector3.zero, 0, true, destroyOnLoad);
|
|
}
|
|
|
|
public SoundEffectInstance PlayFirstClipAt(Vector3 position)
|
|
{
|
|
return PlayInternal(position, 0, true);
|
|
}
|
|
|
|
public SoundEffectInstance PlayFirstClipWithDelayAt(Vector3 position, float delay)
|
|
{
|
|
return PlayInternal(position, delay, true);
|
|
}
|
|
|
|
SoundEffectInstance PlayInternal(Vector3 position, float delay, bool firstClip = false, bool destroyOnLoad = true)
|
|
{
|
|
var options = ToOptions();
|
|
options.delay = delay;
|
|
options.destroyOnLoad = destroyOnLoad;
|
|
|
|
AudioClip clip;
|
|
if (firstClip)
|
|
{
|
|
clip = clips[0];
|
|
}
|
|
else
|
|
{
|
|
int rngIndex = Random.Range(0, clips.Count);
|
|
clip = clips[rngIndex];
|
|
}
|
|
|
|
var time = Time.time;
|
|
|
|
if (!Mathf.Approximately(maxPlayInterval, 0))
|
|
{
|
|
if (time - lastPlayTime < maxPlayInterval)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
lastPlayTime = time;
|
|
|
|
var gameObject = new GameObject($"{this.name} -- {clip.name}");
|
|
gameObject.SetActive(false);
|
|
gameObject.transform.position = position;
|
|
|
|
if (!options.volume.HasValue)
|
|
{
|
|
options.volume = defaultVolume;
|
|
}
|
|
|
|
options.volume += additionalGain;
|
|
|
|
var soundEffectInstance = gameObject.AddComponent<SoundEffectInstance>();
|
|
soundEffectInstance.clip = clip;
|
|
soundEffectInstance.options = options;
|
|
|
|
gameObject.SetActive(true);
|
|
|
|
return soundEffectInstance;
|
|
}
|
|
}
|
|
}
|