//### Particles Static Bezier Flow Controller //This is a component that controlls behaviour of particle system mounted to the same game object it is. // //It controlls only particles path, it does not controll any other aspect ot their behaviour or loock. // //License information: [ASSET STORE TERMS OF SERVICE AND EULA](https://unity3d.com/legal/as_terms) // //Developed by [MathArtCode](https://www.assetstore.unity3d.com/en/#!/search/page=1/sortby=popularity/query=publisher:8738) team, 2015 using System; using System.Collections.Generic; using Assets.Scripts.BezierCurvedParticlesFlow.Utilities; using UnityEngine; #if !UNITY_3_5 namespace Assets.Scripts.BezierCurvedParticlesFlow { #endif [AddComponentMenu( "Effects/MathArtCode/Particles Static Bezier Flow" )] [ExecuteInEditMode] [RequireComponent(typeof (ParticleSystem))] public sealed class ParticlesStaticBezierFlowController : MonoBehaviour { [SerializeField] private BezierLogic _bezierLogicLogic; private ParticleSystem.Particle[] _particles; [SerializeField] private Vector3[] _positions; [SerializeField] private int _samplesCount; private ParticleSystem _system; [SerializeField] private bool _usePositions; [SerializeField] private bool _useVelocities; [SerializeField] private Vector3[] _velocities; #if UNITY_3_5 [SerializeField] private int _maxParticles; //Unity3.5 ParticleSystem.MaxParticles public int MaxParticles { get { return _maxParticles; } set { _maxParticles = value; _particles = new ParticleSystem.Particle[_maxParticles]; } } #endif //Stores baked positions relative to host game object. private Vector3[] Positions { get { if (_positions == null) { Rasterize(); } return _positions; } } //Stores baked velocities relative to host game object. private Vector3[] Velocities { get { if (_velocities == null) { Rasterize(); } return _velocities; } } //Defines if pixel perfect positions as they are defined in bezier curve shall be used (which makes all particles follow one curve). public bool UsePositions { get { return _usePositions; } set { _usePositions = value; } } //Defines if each particle shall set its velocity relative to its life time (allowing you to use particle emmiter shape as flow form). public bool UseVelocities { get { return _useVelocities; } set { _useVelocities = value; } } //Hosts main curve related logic public BezierLogic BezierLogic { get { return _bezierLogicLogic ?? (_bezierLogicLogic = new BezierLogic()); } } //Defines how much samples shall be used in the resulting curve (sets size of arrays of positions and velocities updated on `Rasterize()` call). public int SamplesCount { get { return _samplesCount; } set { _samplesCount = value; } } //Allows to get a position which shall be taken by particle relative to its life time. private Vector3 GetPoint(float t) { t = Mathf.Clamp01(t)*(_samplesCount - 1); var i = (int) t; if (i >= Positions.Length) { i = Positions.Length-1; } return Positions[i]; } //Allows to get a velocity which shall be taken by particle relative to its life time. private Vector3 GetVelocity(float t) { t = Mathf.Clamp01(t)*(_samplesCount - 1); var i = (int) t; if (i >= Velocities.Length) { i = Velocities.Length-1; } return Velocities[i]; } //Updates baked values private void SetBakedData(Vector3[] positions, Vector3[] velocities) { _positions = positions; _velocities = velocities; } //Recalculates and updates baked values public void Rasterize() { var positions = new List(); var velocities = new List(); for (var i = 1; i < _samplesCount; i++) { var t = i/(float) _samplesCount; positions.Add(BezierLogic.GetPoint(t)); velocities.Add(BezierLogic.GetVelocity(t)); } SetBakedData(positions.ToArray(), velocities.ToArray()); } //Resets component to its default values // ReSharper disable once UnusedMember.Local private void Reset() { #if UNITY_3_5 _maxParticles = 50; #endif _samplesCount = 50; BezierLogic.Reset(); Rasterize(); _usePositions = true; _usePositions = true; } //Updates `ParticleSystem` particles setting positions and velocities if needed // ReSharper disable once UnusedMember.Local private void LateUpdate() { InitializeIfNeeded(); var numParticlesAlive = _system.GetParticles(_particles); for (var i = 0; i < numParticlesAlive; i++) { var p = _particles[i]; var t = (p.startLifetime - p.remainingLifetime)/p.startLifetime; if (_useVelocities) { _particles[i].velocity = GetVelocity(t); } if (_usePositions) { _particles[i].position = GetPoint(t); } } _system.SetParticles(_particles, numParticlesAlive); } //Gets GameObject particle system private void InitializeIfNeeded() { if (_system == null) { _system = GetComponent(); } if ( _particles == null ) { #if !UNITY_3_5 _particles = new ParticleSystem.Particle[_system.maxParticles]; #else _particles = new ParticleSystem.Particle[_maxParticles]; #endif _system.GetParticles( _particles ); } } } #if !UNITY_3_5 } #endif