123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- //
- // Rain Maker (c) 2015 Digital Ruby, LLC
- // http://www.digitalruby.com
- //
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.Audio;
- namespace DigitalRuby.RainMaker
- {
- public class BaseRainScript : MonoBehaviour
- {
- [Tooltip("Camera the rain should hover over, defaults to main camera")]
- public Camera Camera;
- [Tooltip("Whether rain should follow the camera. If false, rain must be moved manually and will not follow the camera.")]
- public bool FollowCamera = true;
- [Tooltip("Light rain looping clip")]
- public AudioClip RainSoundLight;
- [Tooltip("Medium rain looping clip")]
- public AudioClip RainSoundMedium;
- [Tooltip("Heavy rain looping clip")]
- public AudioClip RainSoundHeavy;
- [Tooltip("AudoMixer used for the rain sound")]
- public AudioMixerGroup RainSoundAudioMixer;
- [Tooltip("Intensity of rain (0-1)")]
- [Range(0.0f, 1.0f)]
- public float RainIntensity;
- [Tooltip("Rain particle system")]
- public ParticleSystem RainFallParticleSystem;
- [Tooltip("Particles system for when rain hits something")]
- public ParticleSystem RainExplosionParticleSystem;
- [Tooltip("Particle system to use for rain mist")]
- public ParticleSystem RainMistParticleSystem;
- [Tooltip("The threshold for intensity (0 - 1) at which mist starts to appear")]
- [Range(0.0f, 1.0f)]
- public float RainMistThreshold = 0.5f;
- [Tooltip("Wind looping clip")]
- public AudioClip WindSound;
- [Tooltip("Wind sound volume modifier, use this to lower your sound if it's too loud.")]
- public float WindSoundVolumeModifier = 0.5f;
- [Tooltip("Wind zone that will affect and follow the rain")]
- public WindZone WindZone;
- [Tooltip("X = minimum wind speed. Y = maximum wind speed. Z = sound multiplier. Wind speed is divided by Z to get sound multiplier value. Set Z to lower than Y to increase wind sound volume, or higher to decrease wind sound volume.")]
- public Vector3 WindSpeedRange = new Vector3(50.0f, 500.0f, 500.0f);
- [Tooltip("How often the wind speed and direction changes (minimum and maximum change interval in seconds)")]
- public Vector2 WindChangeInterval = new Vector2(5.0f, 30.0f);
- [Tooltip("Whether wind should be enabled.")]
- public bool EnableWind = true;
- protected LoopingAudioSource audioSourceRainLight;
- protected LoopingAudioSource audioSourceRainMedium;
- protected LoopingAudioSource audioSourceRainHeavy;
- protected LoopingAudioSource audioSourceRainCurrent;
- protected LoopingAudioSource audioSourceWind;
- protected Material rainMaterial;
- protected Material rainExplosionMaterial;
- protected Material rainMistMaterial;
- private float lastRainIntensityValue = -1.0f;
- private float nextWindTime;
- private void UpdateWind()
- {
- if (EnableWind && WindZone != null && WindSpeedRange.y > 1.0f)
- {
- WindZone.gameObject.SetActive(true);
- if (FollowCamera)
- {
- WindZone.transform.position = Camera.transform.position;
- }
- if (!Camera.orthographic)
- {
- WindZone.transform.Translate(0.0f, WindZone.radius, 0.0f);
- }
- if (nextWindTime < Time.time)
- {
- WindZone.windMain = UnityEngine.Random.Range(WindSpeedRange.x, WindSpeedRange.y);
- WindZone.windTurbulence = UnityEngine.Random.Range(WindSpeedRange.x, WindSpeedRange.y);
- if (Camera.orthographic)
- {
- int val = UnityEngine.Random.Range(0, 2);
- WindZone.transform.rotation = Quaternion.Euler(0.0f, (val == 0 ? 90.0f : -90.0f), 0.0f);
- }
- else
- {
- WindZone.transform.rotation = Quaternion.Euler(UnityEngine.Random.Range(-30.0f, 30.0f), UnityEngine.Random.Range(0.0f, 360.0f), 0.0f);
- }
- nextWindTime = Time.time + UnityEngine.Random.Range(WindChangeInterval.x, WindChangeInterval.y);
- if (audioSourceWind != default)
- {
- audioSourceWind.Play((WindZone.windMain / WindSpeedRange.z) * WindSoundVolumeModifier);
- }
- }
- }
- else
- {
- if (WindZone != null)
- {
- WindZone.gameObject.SetActive(false);
- }
- audioSourceWind.Stop();
- }
- if (audioSourceWind != default)
- {
- audioSourceWind.Update();
- }
- }
- private void CheckForRainChange()
- {
- if (lastRainIntensityValue != RainIntensity)
- {
- lastRainIntensityValue = RainIntensity;
- if (RainIntensity <= 0.01f)
- {
- if (audioSourceRainCurrent != null)
- {
- audioSourceRainCurrent.Stop();
- audioSourceRainCurrent = null;
- }
- if (RainFallParticleSystem != null)
- {
- ParticleSystem.EmissionModule e = RainFallParticleSystem.emission;
- e.enabled = false;
- RainFallParticleSystem.Stop();
- }
- if (RainMistParticleSystem != null)
- {
- ParticleSystem.EmissionModule e = RainMistParticleSystem.emission;
- e.enabled = false;
- RainMistParticleSystem.Stop();
- }
- }
- else
- {
- LoopingAudioSource newSource;
- if (RainIntensity >= 0.67f)
- {
- newSource = audioSourceRainHeavy;
- }
- else if (RainIntensity >= 0.33f)
- {
- newSource = audioSourceRainMedium;
- }
- else
- {
- newSource = audioSourceRainLight;
- }
- if (audioSourceRainCurrent != newSource)
- {
- if (audioSourceRainCurrent != null)
- {
- audioSourceRainCurrent.Stop();
- }
- audioSourceRainCurrent = newSource;
- audioSourceRainCurrent.Play(1.0f);
- }
- if (RainFallParticleSystem != null)
- {
- ParticleSystem.EmissionModule e = RainFallParticleSystem.emission;
- e.enabled = RainFallParticleSystem.GetComponent<Renderer>().enabled = true;
- if (!RainFallParticleSystem.isPlaying)
- {
- RainFallParticleSystem.Play();
- }
- ParticleSystem.MinMaxCurve rate = e.rateOverTime;
- rate.mode = ParticleSystemCurveMode.Constant;
- rate.constantMin = rate.constantMax = RainFallEmissionRate();
- e.rateOverTime = rate;
- }
- if (RainMistParticleSystem != null)
- {
- ParticleSystem.EmissionModule e = RainMistParticleSystem.emission;
- e.enabled = RainMistParticleSystem.GetComponent<Renderer>().enabled = true;
- if (!RainMistParticleSystem.isPlaying)
- {
- RainMistParticleSystem.Play();
- }
- float emissionRate;
- if (RainIntensity < RainMistThreshold)
- {
- emissionRate = 0.0f;
- }
- else
- {
- // must have RainMistThreshold or higher rain intensity to start seeing mist
- emissionRate = MistEmissionRate();
- }
- ParticleSystem.MinMaxCurve rate = e.rateOverTime;
- rate.mode = ParticleSystemCurveMode.Constant;
- rate.constantMin = rate.constantMax = emissionRate;
- e.rateOverTime = rate;
- }
- }
- }
- }
- protected virtual void Start()
- {
- #if DEBUG
- if (RainFallParticleSystem == null)
- {
- Debug.LogError("Rain fall particle system must be set to a particle system");
- return;
- }
- #endif
- if (Camera == null)
- {
- Camera = Camera.main;
- }
- audioSourceRainLight = new LoopingAudioSource(this, RainSoundLight, RainSoundAudioMixer);
- audioSourceRainMedium = new LoopingAudioSource(this, RainSoundMedium, RainSoundAudioMixer);
- audioSourceRainHeavy = new LoopingAudioSource(this, RainSoundHeavy, RainSoundAudioMixer);
- audioSourceWind = new LoopingAudioSource(this, WindSound, RainSoundAudioMixer);
- if (RainFallParticleSystem != null)
- {
- ParticleSystem.EmissionModule e = RainFallParticleSystem.emission;
- e.enabled = false;
- Renderer rainRenderer = RainFallParticleSystem.GetComponent<Renderer>();
- rainRenderer.enabled = false;
- rainMaterial = new Material(rainRenderer.material);
- rainMaterial.EnableKeyword("SOFTPARTICLES_OFF");
- rainRenderer.material = rainMaterial;
- }
- if (RainExplosionParticleSystem != null)
- {
- ParticleSystem.EmissionModule e = RainExplosionParticleSystem.emission;
- e.enabled = false;
- Renderer rainRenderer = RainExplosionParticleSystem.GetComponent<Renderer>();
- rainExplosionMaterial = new Material(rainRenderer.material);
- rainExplosionMaterial.EnableKeyword("SOFTPARTICLES_OFF");
- rainRenderer.material = rainExplosionMaterial;
- }
- if (RainMistParticleSystem != null)
- {
- ParticleSystem.EmissionModule e = RainMistParticleSystem.emission;
- e.enabled = false;
- Renderer rainRenderer = RainMistParticleSystem.GetComponent<Renderer>();
- rainRenderer.enabled = false;
- rainMistMaterial = new Material(rainRenderer.material);
- if (UseRainMistSoftParticles)
- {
- rainMistMaterial.EnableKeyword("SOFTPARTICLES_ON");
- }
- else
- {
- rainMistMaterial.EnableKeyword("SOFTPARTICLES_OFF");
- }
- rainRenderer.material = rainMistMaterial;
- }
- }
- protected virtual void Update()
- {
- #if DEBUG
- if (RainFallParticleSystem == null)
- {
- Debug.LogError("Rain fall particle system must be set to a particle system");
- return;
- }
- #endif
- CheckForRainChange();
- UpdateWind();
- if (audioSourceRainLight != default)
- {
- audioSourceRainLight.Update();
- audioSourceRainMedium.Update();
- audioSourceRainHeavy.Update();
- }
- }
-
- protected virtual float RainFallEmissionRate()
- {
- return (RainFallParticleSystem.main.maxParticles / RainFallParticleSystem.main.startLifetime.constant) * RainIntensity;
- }
- protected virtual float MistEmissionRate()
- {
- return (RainMistParticleSystem.main.maxParticles / RainMistParticleSystem.main.startLifetime.constant) * RainIntensity * RainIntensity;
- }
- protected virtual bool UseRainMistSoftParticles
- {
- get
- {
- return true;
- }
- }
- }
- /// <summary>
- /// Provides an easy wrapper to looping audio sources with nice transitions for volume when starting and stopping
- /// </summary>
- public class LoopingAudioSource
- {
- public AudioSource AudioSource { get; private set; }
- public float TargetVolume { get; private set; }
- public LoopingAudioSource(MonoBehaviour script, AudioClip clip, AudioMixerGroup mixer)
- {
- AudioSource = script.gameObject.AddComponent<AudioSource>();
- if (mixer != null)
- {
- AudioSource.outputAudioMixerGroup = mixer;
- }
- AudioSource.loop = true;
- AudioSource.clip = clip;
- AudioSource.playOnAwake = false;
- AudioSource.volume = 0.0f;
- AudioSource.Stop();
- TargetVolume = 1.0f;
- }
- public void Play(float targetVolume)
- {
- if (!AudioSource.isPlaying)
- {
- AudioSource.volume = 0.0f;
- AudioSource.Play();
- }
- TargetVolume = targetVolume;
- }
- public void Stop()
- {
- TargetVolume = 0.0f;
- }
- public void Update()
- {
- if (AudioSource.isPlaying && (AudioSource.volume = Mathf.Lerp(AudioSource.volume, TargetVolume, Time.deltaTime)) == 0.0f)
- {
- AudioSource.Stop();
- }
- }
-
- }
- }
|