123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.Audio;
- using QFSW.MOP2;
- using UnityEngine.SceneManagement;
- using Sirenix.OdinInspector;
- namespace KairoEngine.SFX
- {
- // Todo: Remove playing SFX on scene change
-
- public class SoundEmitter : MonoBehaviour
- {
- public SphereCollider trigger;
- public AudioSource audioSource;
- [ReadOnly]
- public AudioClip audioClip;
- public SFXClip sfx;
- public string soundEmitterPrefabPool = "";
- private float fadeInTime;
- private float fadeOutTime;
- private Coroutine fadeOutCoroutine;
- private bool done = false;
- /// <summary>
- /// play a sound at a location in the world using an Audio Clip.
- /// </summary>
- /// <param name="audioClip">The audio clip to be played</param>
- /// <param name="location">The Vector3 position to play the sound in the world</param>
- /// <param name="volume">Audio clip volume</param>
- /// <param name="radius">Radius for SoundSensors</param>
- /// <param name="audioMixerGroup">Audio Mixer Channel</param>
- /// <param name="world">Trigger SoundSensors in world?</param>
- public void Initialize(AudioClip audioClip, Vector3 location, float volume, float radius, AudioMixerGroup audioMixerGroup, bool world = true)
- {
- this.audioClip = audioClip;
- this.trigger.radius = radius;
- transform.position = location;
- this.audioSource.volume = volume;
- this.audioSource.outputAudioMixerGroup = audioMixerGroup;
- this.audioSource.clip = this.audioClip;
- this.done = false;
- if(world == false)
- {
- trigger.enabled = false;
- }
- this.audioSource.Play();
- }
- /// <summary>
- /// Play a sound at a location in the world using a SFX Clip.
- /// </summary>
- /// <param name="sfx">SFX Clip with audio clip and parameters.</param>
- /// <param name="location">Vector3 representing the location to play the sound.</param>
- public void Initialize(SFXClip sfx, Vector3 location)
- {
- this.sfx = sfx;
- this.done = false;
- // Audio Clip
- if(sfx.sfxType == SFXClipType.Single)
- {
- // Single
- this.audioClip = sfx.clip;
- }
- else if(sfx.sfxType == SFXClipType.RandomList)
- {
- // Random from list
- this.audioClip = sfx.clips[Random.Range(0, sfx.clips.Count)];
- }
- this.audioSource.clip = this.audioClip;
- // Sound Location
- transform.position = location;
- // Audio Mixer Channel
- this.audioSource.outputAudioMixerGroup = sfx.audioMixerChannel;
- // Loop
- if(sfx.sfxType == SFXClipType.Single) this.audioSource.loop = sfx.loop;
- // Volume
- this.audioSource.volume = sfx.volume + Random.Range(-sfx.volumeVariation, sfx.volumeVariation);
- // Pitch
- this.audioSource.pitch = sfx.pitch + Random.Range(-sfx.pitchVariation, sfx.pitchVariation);
- // Spatial or stereo audio
- if(sfx.soundSpace != SFXSpace.Stereo)
- {
- this.audioSource.spatialize = true;
- }
- else
- {
- this.audioSource.spatialize = false;
- this.audioSource.spatialBlend = 0;
- }
- // Pan
- if(sfx.soundSpace != SFXSpace.GameWorld)
- {
- // Stereo audio Pan
- this.audioSource.panStereo = sfx.pan + Random.Range(-sfx.panVariation, sfx.panVariation);
- }
- else
- {
- // 3D audio has no Pan
- this.audioSource.panStereo = 0;
- }
- // Spatial Blend
- if(sfx.soundSpace == SFXSpace.Mix)
- {
- this.audioSource.spatialBlend = sfx.spatialBlend + Random.Range(-sfx.spatialBlendVariation, sfx.spatialBlendVariation);
- }
- // Set Distance
- if(sfx.soundSpace == SFXSpace.GameWorld || sfx.soundSpace == SFXSpace.Mix)
- {
- this.audioSource.minDistance = sfx.minDistance;
- this.audioSource.maxDistance = sfx.maxDistance;
- }
- // Use world sensor
- if(sfx.sensorDetection == true)
- {
- trigger.enabled = true;
- this.trigger.radius = sfx.soundRadius;
- }
- else trigger.enabled = true;
- // Set Fade In
- if(sfx.fadeIn)
- {
- this.audioSource.volume = 0f;
- this.fadeInTime = 0f;
- StartCoroutine(FadeIn());
- }
- // Set Fade out
- if(sfx.fadeOut)
- {
- fadeOutTime = 0f;
- fadeOutCoroutine = StartCoroutine(FadeOut());
- }
- // Set Remove on scene change
- // ! Turn this on when dependencies are solved
- //if(sfx.removeOnSceneChange) TransitionEvents.OnChangeScene += OnSceneChanged;
- // Trim and Play the audio clip
- if(sfx.trim) this.audioSource.time = sfx.trimStartDuration;
- this.audioSource.Play();
- if(sfx.trim) this.audioSource.SetScheduledEndTime(AudioSettings.dspTime +(sfx.trimEndDuration - sfx.trimStartDuration));
- }
- void Update()
- {
- if(done == true) return;
- // Destroy this Gameobject when the sound is done playing
- if(audioSource.isPlaying == false)
- {
- if(sfx == null) return;
- if(sfx.loop && sfx.sfxType == SFXClipType.RandomList)
- {
- Initialize(sfx, transform.position);
- }
- else
- {
- Remove();
- }
- }
-
- }
- private void Remove()
- {
- SoundController.soundEmitters.Remove(this);
- // ! Enable when dependencies are resolved
- //if(sfx.removeOnSceneChange) TransitionEvents.OnChangeScene -= OnSceneChanged;
- sfx = null;
- if(MasterObjectPooler.Instance != null && soundEmitterPrefabPool != "") MasterObjectPooler.Instance.GetPool(soundEmitterPrefabPool).Release(this.gameObject);
- else Destroy(this.gameObject);
- }
- IEnumerator FadeIn()
- {
- float start = Time.realtimeSinceStartup;
- while(Time.realtimeSinceStartup <= (start + (sfx.fadeInDuration)))
- {
- fadeInTime = (Time.realtimeSinceStartup - start);
- this.audioSource.volume = Mathf.Lerp(0, 1, fadeInTime/sfx.fadeInDuration);
- yield return null;
- }
- this.audioSource.volume = 1;
- }
- IEnumerator FadeOut(bool wait = true, bool remove = false, float time = 0)
- {
- fadeOutTime = 0f;
- if(time == 0) time = sfx.fadeOutDuration;
- if(wait) yield return new WaitForSecondsRealtime((this.audioSource.clip.length - this.audioSource.time) - time);
- if(sfx == null) yield return 0;
- float start = Time.realtimeSinceStartup;
- while(Time.realtimeSinceStartup < (start + (time)))
- {
- fadeOutTime = (Time.realtimeSinceStartup - start);
- this.audioSource.volume = Mathf.Lerp(1, 0, fadeOutTime/time);
- yield return null;
- }
- this.audioSource.volume = 0;
- if(remove) Remove();
- }
- // ! Enable when dependencies are solved
- /*
- private void OnSceneChanged(SceneChangeData sceneData, float time)
- {
- StopCoroutine(fadeOutCoroutine);
- done = true;
- if(sfx == null) return;
- if(sfx.fadeOut) StartCoroutine(FadeOut(false, true, time));
- else Remove();
- }
- */
- }
- }
|