// // 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 UnityEngine; using System.Collections; using System; namespace DigitalRuby.ThunderAndLightning { /// /// Lightning whip spell, think Balrog but with lightning instead of fire /// public class LightningWhipSpell : LightningSpellScript { /// Attach the whip to what object [Header("Whip")] [Tooltip("Attach the whip to what object")] public GameObject AttachTo; /// Rotate the whip with this object [Tooltip("Rotate the whip with this object")] public GameObject RotateWith; /// Whip handle [Tooltip("Whip handle")] public GameObject WhipHandle; /// Whip start [Tooltip("Whip start")] public GameObject WhipStart; /// Whip spring [Tooltip("Whip spring")] public GameObject WhipSpring; /// Whip crack audio source [Tooltip("Whip crack audio source")] public AudioSource WhipCrackAudioSource; /// /// Callback for when the whip strikes a point /// [HideInInspector] public Action CollisionCallback; private IEnumerator WhipForward() { const float distanceBack = 25.0f; const float springForwardTime = 0.10f; const float springBackwardTime = 0.25f; const float strikeWaitTime = 0.1f; const float recoilWaitTime = 0.1f; // remove the drag from all objects so they can move rapidly without decay for (int i = 0; i < WhipStart.transform.childCount; i++) { GameObject obj = WhipStart.transform.GetChild(i).gameObject; Rigidbody rb = obj.GetComponent(); if (rb != null) { rb.drag = 0.0f; rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; } } // activate the spring WhipSpring.SetActive(true); Vector3 anchor = WhipStart.GetComponent().position; // calculate the forward position first RaycastHit hit; Vector3 whipPositionForwards, whipPositionBackwards; if (Physics.Raycast(anchor, Direction, out hit, MaxDistance, CollisionMask)) { Vector3 dir = (hit.point - anchor).normalized; whipPositionForwards = anchor + (dir * MaxDistance); // put the spring behind the whip to yank it back in the opposite of the direction whipPositionBackwards = anchor - (dir * distanceBack); } else { whipPositionForwards = anchor + (Direction * MaxDistance); // put the spring behind the whip to yank it back in the opposite of the direction whipPositionBackwards = anchor - (Direction * distanceBack); } //whipPositionBackwards -= (WhipStart.transform.forward * distanceBack); //whipPositionBackwards += (WhipStart.transform.up * 5.0f); // set back position WhipSpring.GetComponent().position = whipPositionBackwards; // wait a bit yield return WaitForSecondsLightning.WaitForSecondsLightningPooled(springBackwardTime); // now put the spring in front of the whip to pull it forward WhipSpring.GetComponent().position = whipPositionForwards; yield return WaitForSecondsLightning.WaitForSecondsLightningPooled(springForwardTime); // play whip crack sound if (WhipCrackAudioSource != null) { WhipCrackAudioSource.Play(); } yield return WaitForSecondsLightning.WaitForSecondsLightningPooled(strikeWaitTime); // show the strike paticle system if (CollisionParticleSystem != null) { CollisionParticleSystem.Play(); } // create collision wherever the whip hit ApplyCollisionForce(SpellEnd.transform.position); // turn off the spring WhipSpring.SetActive(false); if (CollisionCallback != null) { CollisionCallback(SpellEnd.transform.position); } // wait a bit longer for the whip to recoil yield return WaitForSecondsLightning.WaitForSecondsLightningPooled(recoilWaitTime); // put the drag back on for (int i = 0; i < WhipStart.transform.childCount; i++) { GameObject obj = WhipStart.transform.GetChild(i).gameObject; Rigidbody rb = obj.GetComponent(); if (rb != null) { rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; rb.drag = 0.5f; } } } /// /// Start /// protected override void Start() { base.Start(); WhipSpring.SetActive(false); WhipHandle.SetActive(false); } /// /// Update /// protected override void Update() { base.Update(); gameObject.transform.position = AttachTo.transform.position; gameObject.transform.rotation = RotateWith.transform.rotation; } /// /// Fires when spell is cast /// protected override void OnCastSpell() { StartCoroutine(WhipForward()); } /// /// Fires when spell is stopped /// protected override void OnStopSpell() { } /// /// Fires when spell is activated /// protected override void OnActivated() { base.OnActivated(); WhipHandle.SetActive(true); } /// /// Fires when spell is deactivated /// protected override void OnDeactivated() { base.OnDeactivated(); WhipHandle.SetActive(false); } } }