using System; using UnityEngine; using System.Collections; namespace Tenkoku.Core { public class TenkokuLightningFX : MonoBehaviour { //Public Variables public bool startLightning = false; public float lightningFrequency = 10.0f; public float lightningDistance = 1.0f; public float lightningSpeed = 2.0f; public float lightningSysTime = 1.0f; public float lightningIntensity = 5.0f; public float lightningDirection = 180.0f; public float lightningRandomRange = 0.0f; public bool lightningUseLight = false; public Vector3 boltPosStart; public float boltLength = 2100.0f; public float boltWidth = 100.0f; public int boltPoints = 50; public AudioClip[] audioThunderDist; public AudioClip[] audioThunderMed; public AudioClip[] audioThunderNear; public GameObject[] thunderObjects; //Private Variables private Vector3 lightningUseVec; private Light lightningLight; private Transform lightningTrans; private float lightningUseInt = 0.0f; private float lightningFreqTime = 0.0f; private float useLightningFrequency = 1.0f; private float lightningTime = 0.0f; private float useLightningSysTime = 0.0f; private float boltTime = 0.0f; private Tenkoku.Core.Random lightningRand; private int srSeed; private float useLightningRandPos = 0.0f; private Light lightObjectWorld; private Light lightObjectNight; private LineRenderer lightningLine; private Transform lightningLineTrans; private AudioSource thunderObject; private AudioSource[] thunderAudio; private int currAudio = -1; private bool startThunder = false; private Tenkoku.Core.TenkokuModule tenkokuModule; private float[] thunderVolume; private float savefrequency = -1.0f; //collect for GC private float volEnable; private int tX; private float freq; private int vX; private Vector3[] lPositions; private Vector3 usePos; private float xR; private Vector3 sPos; private int px; private AudioClip useAudio; private float thunderDelay = 0.0f; private float thunderVol = 1.0f; private float thunderPitch = 1.0f; private Vector3 thunderPosition = Vector3.zero; private Vector3 lightningLightPosition = Vector3.zero; private float _time; private float _deltaTime; void Start () { //log objects //tenkokuModule = GameObject.Find("Tenkoku DynamicSky").GetComponent() as Tenkoku.Core.TenkokuModule; tenkokuModule = (Tenkoku.Core.TenkokuModule) FindObjectOfType(typeof(Tenkoku.Core.TenkokuModule)); lightningLight = GameObject.Find("LIGHT_Lightning").GetComponent(); lightningTrans = GameObject.Find("LIGHT_Lightning").GetComponent(); lightObjectWorld = GameObject.Find("LIGHT_World").GetComponent(); lightObjectNight = GameObject.Find("LIGHT_NightSky").GetComponent(); lightningLine = GameObject.Find("fxLightningRenderer").gameObject.GetComponent() as LineRenderer; lightningLineTrans = GameObject.Find("fxLightningRenderer").gameObject.GetComponent(); //set random factor //lightningRand = new Tenkoku.Core.Random(System.Environment.TickCount); srSeed = tenkokuModule.randSeed; lightningRand = new Tenkoku.Core.Random(srSeed); //initialize thunder audio objects thunderVolume = new float[5];//Array(5); thunderAudio = new AudioSource[5];//Array(5); for (tX = 0; tX < thunderObjects.Length; tX++){ thunderObjects[tX] = new GameObject(); thunderObjects[tX].AddComponent(); thunderObjects[tX].transform.parent = this.transform; thunderObjects[tX].transform.name = "thunderAudio"+tX.ToString(); thunderAudio[tX] = thunderObjects[tX].GetComponent() as AudioSource; thunderVolume[tX] = 1.0f; } if (lightningLight != null){ lightningLight.renderMode = LightRenderMode.ForceVertex; lightningLight.shadows = LightShadows.None; } } void LateUpdate () { //cache time variables for performance; _time = UnityEngine.Time.time; _deltaTime = UnityEngine.Time.deltaTime; //use Tenkoku Random if (tenkokuModule != null){ if (srSeed != tenkokuModule.randSeed){ srSeed = tenkokuModule.randSeed; lightningRand = new Tenkoku.Core.Random(srSeed); } } if (lightningRand == null){ lightningRand = new Tenkoku.Core.Random(srSeed); } //handle system values freq = tenkokuModule.weather_lightning; lightningDirection = tenkokuModule.weather_lightningDir; lightningRandomRange = tenkokuModule.weather_lightningRange; lightningFrequency = Mathf.Lerp(25.0f,1.0f,freq); lightningIntensity = Mathf.Clamp(Mathf.Lerp(1.0f,10.0f,freq),0.0f,5.0f); //reset based on frequency changes if (freq != savefrequency && freq > 0.0f){ savefrequency = freq; useLightningFrequency = lightningFrequency; } //clamp lightningIntensity = Mathf.Clamp(lightningIntensity,0.0f,10.0f); //enable lightening volEnable = 0.0f; if (tenkokuModule.enableSoundFX) volEnable = 1.0f; if (freq <= 0.0f){ startLightning = false; } //set overall Thunder Volume for (vX = 0; vX < thunderAudio.Length; vX++){ thunderAudio[vX].volume = thunderVolume[vX] * tenkokuModule.volumeThunder * volEnable; } //Lightning Timing if (!startLightning){ lightningUseInt = 0.0f; lightningTime = 0.0f; useLightningSysTime = 0.0f; lightningFreqTime = lightningFreqTime + (_deltaTime/useLightningFrequency); if (lightningFreqTime >= 1.0f) startLightning = true; } else { //init settings if (useLightningSysTime == 0.0f){ lightningDistance = lightningRand.Next(-0.3f,0.6f); lightningDistance = Mathf.Clamp(lightningDistance,0.0f,1.0f); lightningSpeed = lightningRand.Next(5.0f,12.0f); lightningSysTime = lightningRand.Next(0.0f,1.4f); lightningSysTime = Mathf.Clamp(lightningSysTime,0.2f,1.0f); lightningUseLight = false; if (lightningRand.Next(0.0f,1.5f + freq) >= 1.0f) lightningUseLight = true; useLightningRandPos = lightningRand.Next(0.0f-lightningRandomRange,lightningRandomRange); boltTime = 1.0f; lightningFreqTime = 0.0f; useLightningFrequency = lightningRand.Next(lightningFrequency-(lightningFrequency*0.75f),lightningFrequency + (lightningFrequency*0.25f)); } //timers useLightningSysTime = useLightningSysTime + _deltaTime; lightningTime = lightningTime + (_deltaTime * lightningSpeed); if (lightningTime <= 1.0f) lightningUseInt = Mathf.SmoothStep(lightningUseInt,lightningIntensity,lightningTime); if (lightningTime > 1.0f) lightningUseInt = Mathf.SmoothStep(lightningUseInt,0.2f,lightningTime-1.0f); //reset if (useLightningSysTime >= lightningSysTime && lightningTime > 2.0f){ startLightning = false; startThunder = false; } if (lightningTime > 2.0f){ lightningTime = 0.0f; lightningSpeed = lightningRand.Next(5.0f,12.0f); boltTime = boltTime + _deltaTime*lightningRand.Next(2.0f,10.0f); boltPoints = Mathf.FloorToInt(lightningRand.Next(40.0f,80.0f)); } //handle thunder if (!startThunder){ startThunder = true; ThunderHandler(); } } //position lightningUseVec = Quaternion.Euler(Mathf.Lerp(-10.0f,-40.0f,lightningDistance), lightningDirection + useLightningRandPos, 0.0f) * Vector3.forward; //set light if (lightningLight != null){ if (lightningUseLight){ if (!tenkokuModule.allowMultiLights){ lightObjectWorld.enabled = false; lightObjectNight.enabled = false; } lightningUseInt = lightningUseInt * Mathf.Lerp(0.0f, 2.0f, tenkokuModule.lightningColor.a); lightningLight.enabled = true; lightningLightPosition.x = Mathf.Clamp(0f-Mathf.Lerp(0f,-60f,lightningDistance),20f,90f); lightningLightPosition.y = (lightningDirection+useLightningRandPos)-180f; lightningLightPosition.z = 0.0f; lightningTrans.eulerAngles = lightningLightPosition; lightningLight.intensity = lightningUseInt * lightningRand.Next(0.4f,1.0f); lightningLight.color = tenkokuModule.lightningColor; } else { lightningLight.enabled = false; lightningLight.intensity = 0f; } if (lightningLight.intensity <= 0.05f && !tenkokuModule.allowMultiLights){ lightObjectWorld.enabled = true; lightObjectNight.enabled = true; lightningLight.enabled = false; } } //send to shader Shader.SetGlobalVector("Tenkoku_Vec_LightningFwd", lightningUseVec); Shader.SetGlobalFloat("Tenkoku_LightningIntensity", 0.2f * (lightningUseInt + ((1f*(1f-lightningDistance))*lightningUseInt))); Shader.SetGlobalFloat("Tenkoku_LightningLightIntensity", 0.2f*lightningLight.intensity); Shader.SetGlobalColor("Tenkoku_LightningColor", tenkokuModule.lightningColor); //------------------------- //### Bolt Rendering ### //------------------------- if (Camera.main != null){ lightningLineTrans.position = Camera.main.transform.position; //lightningLine.transform.Translate(lightningUseVec * 3000.0f, Space.Self); lightningLineTrans.Translate(lightningUseVec * lightningRand.Next(2000f,3000f), Space.Self); boltPosStart = lightningLineTrans.position; boltPosStart.y = Mathf.Clamp(boltPosStart.y,500.0f,2000f); if (lightningRand != null){ if (boltTime > lightningRand.Next(0.1f,1f) || lightningSysTime == 0f){ boltTime = 0f; if (lightningLine != null){ //init positional array boltPoints = Mathf.FloorToInt(Mathf.Clamp(boltPoints,40,80)); lPositions = new Vector3[boltPoints]; usePos = boltPosStart; //set start position lPositions[0] = boltPosStart; //set positions xR = 0.0f; sPos = usePos; #if UNITY_5_5_OR_NEWER lightningLine.positionCount = lPositions.Length; #else lightningLine.SetVertexCount(lPositions.Length); #endif for (px = 0; px < lPositions.Length; px++){ //set base vertical position sPos.y = usePos.y; sPos.y = sPos.y - ((boltLength/(boltPoints-1))*px); sPos.x = sPos.x - lightningRand.Next(((-100f/(boltPoints-1f))*px),((100f/(boltPoints-1f))*px)); if (px > 0 && px < boltPoints-1){ //set width variance xR = ((px*1f)/(boltLength*1f))*_time; sPos.x = sPos.x - Mathf.PerlinNoise(xR,xR)*lightningRand.Next(-1f,1f) * boltWidth; sPos.z = sPos.z - Mathf.PerlinNoise(xR,xR)*lightningRand.Next(-1f,1f) * boltWidth; //reset variance toward end sPos.x = Mathf.Lerp(sPos.x,usePos.x, ((px*1f)/(boltPoints*1f)) * 0.1f ); sPos.z = Mathf.Lerp(sPos.z,usePos.z, ((px*1f)/(boltPoints*1f)) * 0.5f ); //set height variance sPos.y = sPos.y - Mathf.PerlinNoise(xR,xR)*lightningRand.Next(-1f,1f)*0.5f; } lPositions[px] = sPos; lightningLine.SetPosition(px,lPositions[px]); } } } } } } void ThunderHandler(){ //--------------------------------- //### Thunder Audio Handling ### //--------------------------------- //select audio object from pool currAudio += 1; if (currAudio >= thunderObjects.Length) currAudio = 0; if (thunderObjects[currAudio] != null) thunderObject = thunderObjects[currAudio].GetComponent() as AudioSource; //Handle Audio effects if (thunderObject != null){ thunderDelay = 0f; thunderVol = 1f; thunderPitch = 1f; //set audio position if (Camera.main != null){ thunderObject.transform.position = Camera.main.transform.position; thunderObject.transform.Translate(lightningUseVec * 50.0f, Space.Self); thunderPosition.x = thunderObject.transform.position.x; thunderPosition.y = Camera.main.transform.position.y; thunderPosition.z = thunderObject.transform.position.z; thunderObject.transform.position = thunderPosition; } //distant if (!lightningUseLight){ if (lightningDistance < 0.4f){ useAudio = audioThunderDist[Mathf.FloorToInt(lightningRand.Next(0f,audioThunderDist.Length*0.99f))]; thunderDelay = lightningRand.Next(0.7f,2.0f); thunderVol = lightningRand.Next(0.2f,0.4f); thunderPitch = lightningRand.Next(0.6f,0.8f); } if (lightningDistance >= 0.4f){ useAudio = audioThunderMed[Mathf.FloorToInt(lightningRand.Next(0f,audioThunderMed.Length*0.99f))]; thunderDelay = lightningRand.Next(0.7f,1.5f); thunderVol = lightningRand.Next(0.4f,0.6f); thunderPitch = lightningRand.Next(0.8f,0.9f); } } if (lightningUseLight){ if (lightningDistance < 0.4f){ useAudio = audioThunderMed[Mathf.FloorToInt(lightningRand.Next(0f,audioThunderMed.Length*0.99f))]; thunderDelay = lightningRand.Next(0.1f,0.4f); thunderVol = lightningRand.Next(0.5f,0.8f); thunderPitch = lightningRand.Next(0.8f,1.0f); } if (lightningDistance >= 0.4f){ useAudio = audioThunderNear[Mathf.FloorToInt(lightningRand.Next(0.0f,audioThunderNear.Length*0.99f))]; thunderDelay = 0.0f;//lightningRand.Next(0.0,0.0f); thunderVol = lightningRand.Next(0.8f,1.0f); thunderPitch = lightningRand.Next(0.9f,1.2f); } } //Play Sound if (useAudio != null){ //set overall settings thunderObject.spatialBlend = 0.75f; thunderObject.minDistance = 50.0f; thunderObject.maxDistance = 500.0f; thunderObject.spread = 0f; //set clip specific settings thunderObject.clip = useAudio; thunderObject.loop = false; thunderVolume[currAudio] = thunderVol*1.4f; thunderObject.volume = thunderVol*1.4f; thunderObject.pitch = thunderPitch; thunderObject.PlayDelayed(thunderDelay); } } } } }