// // Procedural Lightning for Unity // (c) 2015 Digital Ruby, LLC // Source code may be used for personal or commercial projects. // Source code may NOT be redistributed or sold. // using System.Collections; using System.Collections.Generic; using UnityEngine; namespace DigitalRuby.ThunderAndLightning { /// /// Lightning bolt spell that uses a particle system /// public class LightningParticleSpellScript : LightningSpellScript, ICollisionHandler { /// /// Particle system /// [Header("Particle system")] public ParticleSystem ParticleSystem; /// Particle system collision interval. This time must elapse before another collision will be registered. [Tooltip("Particle system collision interval. This time must elapse before another collision will be registered.")] public float CollisionInterval = 0.0f; /// /// Collision time remaining /// protected float collisionTimer; /// /// Particle system callback. Parameters are game object, collision events, and number of collision events /// [HideInInspector] public System.Action, int> CollisionCallback; /// Whether to enable point lights for the particles [Header("Particle Light Properties")] [Tooltip("Whether to enable point lights for the particles")] public bool EnableParticleLights = true; /// Possible range of colors for particle lights [SingleLineClamp("Possible range for particle lights", 0.001, 100.0f)] public RangeOfFloats ParticleLightRange = new RangeOfFloats { Minimum = 2.0f, Maximum = 5.0f }; /// Possible range of intensity for particle lights [SingleLineClamp("Possible range of intensity for particle lights", 0.01f, 8.0f)] public RangeOfFloats ParticleLightIntensity = new RangeOfFloats { Minimum = 0.2f, Maximum = 0.3f }; /// Possible range of colors for particle lights [Tooltip("Possible range of colors for particle lights")] public Color ParticleLightColor1 = Color.white; /// Possible range of colors for particle lights [Tooltip("Possible range of colors for particle lights")] public Color ParticleLightColor2 = Color.white; /// The culling mask for particle lights [Tooltip("The culling mask for particle lights")] public LayerMask ParticleLightCullingMask = -1; private ParticleSystem.Particle[] particles = new ParticleSystem.Particle[512]; private readonly List particleLights = new List(); private void PopulateParticleLight(Light src) { src.bounceIntensity = 0.0f; src.type = LightType.Point; src.shadows = LightShadows.None; src.color = new Color ( UnityEngine.Random.Range(ParticleLightColor1.r, ParticleLightColor2.r), UnityEngine.Random.Range(ParticleLightColor1.g, ParticleLightColor2.g), UnityEngine.Random.Range(ParticleLightColor1.b, ParticleLightColor2.b), 1.0f ); src.cullingMask = ParticleLightCullingMask; src.intensity = UnityEngine.Random.Range(ParticleLightIntensity.Minimum, ParticleLightIntensity.Maximum); src.range = UnityEngine.Random.Range(ParticleLightRange.Minimum, ParticleLightRange.Maximum); } private void UpdateParticleLights() { if (!EnableParticleLights) { return; } int count = ParticleSystem.GetParticles(particles); while (particleLights.Count < count) { GameObject lightObj = new GameObject("LightningParticleSpellLight"); lightObj.hideFlags = HideFlags.HideAndDontSave; PopulateParticleLight(lightObj.AddComponent()); particleLights.Add(lightObj); } while (particleLights.Count > count) { GameObject.Destroy(particleLights[particleLights.Count - 1]); particleLights.RemoveAt(particleLights.Count - 1); } for (int i = 0; i < count; i++) { particleLights[i].transform.position = particles[i].position; } } private void UpdateParticleSystems() { if (EmissionParticleSystem != null && EmissionParticleSystem.isPlaying) { EmissionParticleSystem.transform.position = SpellStart.transform.position; EmissionParticleSystem.transform.forward = Direction; } if (ParticleSystem != null) { if (ParticleSystem.isPlaying) { ParticleSystem.transform.position = SpellStart.transform.position; ParticleSystem.transform.forward = Direction; } UpdateParticleLights(); } } /// /// OnDestroy /// protected override void OnDestroy() { base.OnDestroy(); foreach (GameObject l in particleLights) { GameObject.Destroy(l); } } /// /// Start /// protected override void Start() { base.Start(); } /// /// Update /// protected override void Update() { base.Update(); UpdateParticleSystems(); collisionTimer -= LightningBoltScript.DeltaTime; } /// /// Fires when spell is cast /// protected override void OnCastSpell() { if (ParticleSystem != null) { ParticleSystem.Play(); UpdateParticleSystems(); } } /// /// Fires when spell is stopped /// protected override void OnStopSpell() { if (ParticleSystem != null) { ParticleSystem.Stop(); } } /// /// Handle a particle collision. Derived classes can override to provide custom logic. /// /// Game Object /// Collisions /// Number of collisions void ICollisionHandler.HandleCollision(GameObject obj, List collisions, int collisionCount) { if (collisionTimer <= 0.0f) { collisionTimer = CollisionInterval; PlayCollisionSound(collisions[0].intersection); ApplyCollisionForce(collisions[0].intersection); if (CollisionCallback != null) { CollisionCallback(obj, collisions, collisionCount); } } } } }