ParticlesStaticBezierFlowController.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. //### Particles Static Bezier Flow Controller
  2. //This is a component that controlls behaviour of particle system mounted to the same game object it is.
  3. //
  4. //It controlls only particles path, it does not controll any other aspect ot their behaviour or loock.
  5. //
  6. //License information: [ASSET STORE TERMS OF SERVICE AND EULA](https://unity3d.com/legal/as_terms)
  7. //
  8. //Developed by [MathArtCode](https://www.assetstore.unity3d.com/en/#!/search/page=1/sortby=popularity/query=publisher:8738) team, 2015
  9. using System;
  10. using System.Collections.Generic;
  11. using Assets.Scripts.BezierCurvedParticlesFlow.Utilities;
  12. using UnityEngine;
  13. #if !UNITY_3_5
  14. namespace Assets.Scripts.BezierCurvedParticlesFlow {
  15. #endif
  16. [AddComponentMenu( "Effects/MathArtCode/Particles Static Bezier Flow" )]
  17. [ExecuteInEditMode]
  18. [RequireComponent(typeof (ParticleSystem))]
  19. public sealed class ParticlesStaticBezierFlowController : MonoBehaviour {
  20. [SerializeField]
  21. private BezierLogic _bezierLogicLogic;
  22. private ParticleSystem.Particle[] _particles;
  23. [SerializeField]
  24. private Vector3[] _positions;
  25. [SerializeField]
  26. private int _samplesCount;
  27. private ParticleSystem _system;
  28. [SerializeField]
  29. private bool _usePositions;
  30. [SerializeField]
  31. private bool _useVelocities;
  32. [SerializeField]
  33. private Vector3[] _velocities;
  34. #if UNITY_3_5
  35. [SerializeField]
  36. private int _maxParticles;
  37. //Unity3.5 ParticleSystem.MaxParticles
  38. public int MaxParticles {
  39. get { return _maxParticles; }
  40. set {
  41. _maxParticles = value;
  42. _particles = new ParticleSystem.Particle[_maxParticles];
  43. }
  44. }
  45. #endif
  46. //Stores baked positions relative to host game object.
  47. private Vector3[] Positions {
  48. get {
  49. if (_positions == null) {
  50. Rasterize();
  51. }
  52. return _positions;
  53. }
  54. }
  55. //Stores baked velocities relative to host game object.
  56. private Vector3[] Velocities {
  57. get {
  58. if (_velocities == null) {
  59. Rasterize();
  60. }
  61. return _velocities;
  62. }
  63. }
  64. //Defines if pixel perfect positions as they are defined in bezier curve shall be used (which makes all particles follow one curve).
  65. public bool UsePositions {
  66. get { return _usePositions; }
  67. set { _usePositions = value; }
  68. }
  69. //Defines if each particle shall set its velocity relative to its life time (allowing you to use particle emmiter shape as flow form).
  70. public bool UseVelocities {
  71. get { return _useVelocities; }
  72. set { _useVelocities = value; }
  73. }
  74. //Hosts main curve related logic
  75. public BezierLogic BezierLogic {
  76. get { return _bezierLogicLogic ?? (_bezierLogicLogic = new BezierLogic()); }
  77. }
  78. //Defines how much samples shall be used in the resulting curve (sets size of arrays of positions and velocities updated on `Rasterize()` call).
  79. public int SamplesCount {
  80. get { return _samplesCount; }
  81. set { _samplesCount = value; }
  82. }
  83. //Allows to get a position which shall be taken by particle relative to its life time.
  84. private Vector3 GetPoint(float t) {
  85. t = Mathf.Clamp01(t)*(_samplesCount - 1);
  86. var i = (int) t;
  87. if (i >= Positions.Length) {
  88. i = Positions.Length-1;
  89. }
  90. return
  91. Positions[i];
  92. }
  93. //Allows to get a velocity which shall be taken by particle relative to its life time.
  94. private Vector3 GetVelocity(float t) {
  95. t = Mathf.Clamp01(t)*(_samplesCount - 1);
  96. var i = (int) t;
  97. if (i >= Velocities.Length) {
  98. i = Velocities.Length-1;
  99. }
  100. return
  101. Velocities[i];
  102. }
  103. //Updates baked values
  104. private void SetBakedData(Vector3[] positions, Vector3[] velocities) {
  105. _positions = positions;
  106. _velocities = velocities;
  107. }
  108. //Recalculates and updates baked values
  109. public void Rasterize() {
  110. var positions = new List<Vector3>();
  111. var velocities = new List<Vector3>();
  112. for (var i = 1; i < _samplesCount; i++) {
  113. var t = i/(float) _samplesCount;
  114. positions.Add(BezierLogic.GetPoint(t));
  115. velocities.Add(BezierLogic.GetVelocity(t));
  116. }
  117. SetBakedData(positions.ToArray(), velocities.ToArray());
  118. }
  119. //Resets component to its default values
  120. // ReSharper disable once UnusedMember.Local
  121. private void Reset() {
  122. #if UNITY_3_5
  123. _maxParticles = 50;
  124. #endif
  125. _samplesCount = 50;
  126. BezierLogic.Reset();
  127. Rasterize();
  128. _usePositions = true;
  129. _usePositions = true;
  130. }
  131. //Updates `ParticleSystem` particles setting positions and velocities if needed
  132. // ReSharper disable once UnusedMember.Local
  133. private void LateUpdate() {
  134. InitializeIfNeeded();
  135. var numParticlesAlive = _system.GetParticles(_particles);
  136. for (var i = 0; i < numParticlesAlive; i++) {
  137. var p = _particles[i];
  138. var t = (p.startLifetime - p.remainingLifetime)/p.startLifetime;
  139. if (_useVelocities) {
  140. _particles[i].velocity = GetVelocity(t);
  141. }
  142. if (_usePositions) {
  143. _particles[i].position = GetPoint(t);
  144. }
  145. }
  146. _system.SetParticles(_particles, numParticlesAlive);
  147. }
  148. //Gets GameObject particle system
  149. private void InitializeIfNeeded() {
  150. if (_system == null) {
  151. _system = GetComponent<ParticleSystem>();
  152. }
  153. if ( _particles == null ) {
  154. #if !UNITY_3_5
  155. _particles = new ParticleSystem.Particle[_system.maxParticles];
  156. #else
  157. _particles = new ParticleSystem.Particle[_maxParticles];
  158. #endif
  159. _system.GetParticles( _particles );
  160. }
  161. }
  162. }
  163. #if !UNITY_3_5
  164. }
  165. #endif