F3DLightning.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. using UnityEngine;
  2. using System.Collections;
  3. [RequireComponent(typeof(LineRenderer))]
  4. public class F3DLightning : MonoBehaviour
  5. {
  6. public LayerMask layerMask;
  7. public Texture[] BeamFrames; // Animation frame sequence
  8. public float FrameStep; // Animation time
  9. public bool RandomizeFrames; // Randomization of animation frames
  10. public int Points; // How many points should be used to construct the beam
  11. public float MaxBeamLength; // Maximum beam length
  12. public float beamScale; // Default beam scale to be kept over distance
  13. public bool AnimateUV; // UV Animation
  14. public float UVTime; // UV Animation speed
  15. public bool Oscillate; // Beam oscillation flag
  16. public float Amplitude; // Beam amplitude
  17. public float OscillateTime; // Beam oscillation rate
  18. public Transform rayImpact; // Impact transform
  19. public Transform rayMuzzle; // Muzzle flash transform
  20. LineRenderer lineRenderer; // Line rendered component
  21. RaycastHit hitPoint; // Raycast structure
  22. int frameNo; // Frame counter
  23. int FrameTimerID; // Frame timer reference
  24. int OscillateTimerID; // Beam oscillation timer reference
  25. float beamLength; // Current beam length
  26. float initialBeamOffset; // Initial UV offset
  27. void Awake()
  28. {
  29. // Get line renderer component
  30. lineRenderer = GetComponent<LineRenderer>();
  31. // Assign first frame texture
  32. if (!AnimateUV && BeamFrames.Length > 0)
  33. lineRenderer.material.mainTexture = BeamFrames[0];
  34. // Randomize uv offset
  35. initialBeamOffset = Random.Range(0f, 5f);
  36. }
  37. // OnSpawned called by pool manager
  38. void OnSpawned()
  39. {
  40. // Start animation sequence if beam frames array has more than 2 elements
  41. if (BeamFrames.Length > 1)
  42. Animate();
  43. // Start oscillation sequence
  44. if (Oscillate && Points > 0)
  45. OscillateTimerID = F3DTime.time.AddTimer(OscillateTime, OnOscillate);
  46. // Play audio
  47. if (F3DAudioController.instance)
  48. F3DAudioController.instance.LightningGunLoop(transform.position, transform);
  49. }
  50. // OnDespawned called by pool manager
  51. void OnDespawned()
  52. {
  53. // Reset frame counter
  54. frameNo = 0;
  55. // Clear frame animation timer
  56. if (FrameTimerID != -1)
  57. {
  58. F3DTime.time.RemoveTimer(FrameTimerID);
  59. FrameTimerID = -1;
  60. }
  61. // Clear oscillation timer
  62. if (OscillateTimerID != -1)
  63. {
  64. F3DTime.time.RemoveTimer(OscillateTimerID);
  65. OscillateTimerID = -1;
  66. }
  67. // Play audio
  68. if (F3DAudioController.instance)
  69. F3DAudioController.instance.LightningGunClose(transform.position);
  70. }
  71. // Hit point calculation
  72. void Raycast()
  73. {
  74. // Prepare structure and create ray
  75. hitPoint = new RaycastHit();
  76. Ray ray = new Ray(transform.position, transform.forward);
  77. // Calculate default beam proportion multiplier based on default scale and maximum length
  78. float propMult = MaxBeamLength * (beamScale / 10f);
  79. // Raycast
  80. if (Physics.Raycast(ray, out hitPoint, MaxBeamLength, layerMask))
  81. {
  82. // Get current beam length
  83. beamLength = Vector3.Distance(transform.position, hitPoint.point);
  84. // Update line renderer
  85. if (!Oscillate)
  86. lineRenderer.SetPosition(1, new Vector3(0f, 0f, beamLength));
  87. // Calculate default beam proportion multiplier based on default scale and current length
  88. propMult = beamLength * (beamScale / 10f);
  89. // Apply hit force to rigidbody
  90. ApplyForce(0.1f);
  91. // Adjust impact effect position
  92. if (rayImpact)
  93. rayImpact.position = hitPoint.point - transform.forward * 0.5f;
  94. }
  95. // Nothing was his
  96. else
  97. {
  98. // Set beam to maximum length
  99. beamLength = MaxBeamLength;
  100. // Update beam length
  101. if (!Oscillate)
  102. lineRenderer.SetPosition(1, new Vector3(0f, 0f, beamLength));
  103. // Adjust impact effect position
  104. if (rayImpact)
  105. rayImpact.position = transform.position + transform.forward * beamLength;
  106. }
  107. // Adjust muzzle position
  108. if (rayMuzzle)
  109. rayMuzzle.position = transform.position + transform.forward * 0.1f;
  110. // Set beam scaling according to its length
  111. lineRenderer.material.SetTextureScale("_MainTex", new Vector2(propMult, 1f));
  112. }
  113. // Generate random noise numbers based on amplitude
  114. float GetRandomNoise()
  115. {
  116. return Random.Range(-Amplitude, Amplitude);
  117. }
  118. // Advance texture frame
  119. void OnFrameStep()
  120. {
  121. // Randomize frame counter
  122. if (RandomizeFrames)
  123. frameNo = Random.Range(0, BeamFrames.Length);
  124. // Set current texture frame based on frame counter
  125. lineRenderer.material.mainTexture = BeamFrames[frameNo];
  126. frameNo++;
  127. // Reset frame counter
  128. if (frameNo == BeamFrames.Length)
  129. frameNo = 0;
  130. }
  131. // Oscillate beam
  132. void OnOscillate()
  133. {
  134. // Calculate number of points based on beam length and default number of points
  135. int points = (int)((beamLength / 10f) * Points);
  136. // Update line rendered segments in case number of points less than 2
  137. if (points < 2)
  138. {
  139. lineRenderer.SetVertexCount(2);
  140. lineRenderer.SetPosition(0, Vector3.zero);
  141. lineRenderer.SetPosition(1, new Vector3(0, 0, beamLength));
  142. }
  143. // Update line renderer segments
  144. else
  145. {
  146. // Update number of points for line renderer
  147. lineRenderer.SetVertexCount(points);
  148. // Set zero point manually
  149. lineRenderer.SetPosition(0, Vector3.zero);
  150. // Update each point with random noise based on amplitude
  151. for (int i = 1; i < points - 1; i++)
  152. lineRenderer.SetPosition(i, new Vector3(GetRandomNoise(), GetRandomNoise(), (beamLength / (points - 1)) * i));
  153. // Set last point manually
  154. lineRenderer.SetPosition(points - 1, new Vector3(0f, 0f, beamLength));
  155. }
  156. }
  157. // Initialize frame animation
  158. void Animate()
  159. {
  160. // Set current frame
  161. frameNo = 0;
  162. lineRenderer.material.mainTexture = BeamFrames[frameNo];
  163. // Add timer
  164. FrameTimerID = F3DTime.time.AddTimer(FrameStep, OnFrameStep);
  165. frameNo = 1;
  166. }
  167. // Apply force to last hit object
  168. void ApplyForce(float force)
  169. {
  170. if (hitPoint.rigidbody != null)
  171. hitPoint.rigidbody.AddForceAtPosition(transform.forward * force, hitPoint.point, ForceMode.VelocityChange);
  172. }
  173. void Update()
  174. {
  175. // Animate texture UV
  176. if (AnimateUV)
  177. lineRenderer.material.SetTextureOffset("_MainTex", new Vector2(Time.time * UVTime + initialBeamOffset, 0f));
  178. // Process raycasting
  179. Raycast();
  180. }
  181. }