96 lines
4.1 KiB
C#
96 lines
4.1 KiB
C#
/// <summary>
|
|
/// SURGE FRAMEWORK
|
|
/// Author: Bob Berkebile
|
|
/// Email: bobb@pixelplacement.com
|
|
///
|
|
/// Forces a referenced particle system to flow along this spline. To optimize performance limit Max Particles to just what is necessary. Particle speed along the path is determined by Start Lifetime.
|
|
///
|
|
/// </summary>
|
|
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using Pixelplacement;
|
|
|
|
[ExecuteInEditMode]
|
|
[RequireComponent (typeof (Spline))]
|
|
public class SplineControlledParticleSystem : MonoBehaviour
|
|
{
|
|
//Public Variables:
|
|
public float startRadius;
|
|
public float endRadius;
|
|
|
|
//Private Variables:
|
|
[SerializeField] ParticleSystem _particleSystem = null;
|
|
Spline _spline;
|
|
ParticleSystem.Particle[] _particles;
|
|
const float _previousDiff = .01f;
|
|
|
|
//Init:
|
|
void Awake ()
|
|
{
|
|
_spline = GetComponent<Spline> ();
|
|
}
|
|
|
|
//Loops:
|
|
void LateUpdate ()
|
|
{
|
|
if (_particleSystem == null) return;
|
|
|
|
if (_particles == null) _particles = new ParticleSystem.Particle[_particleSystem.main.maxParticles];
|
|
|
|
int aliveParticlesCount = _particleSystem.GetParticles (_particles);
|
|
|
|
for (int i = 0; i < aliveParticlesCount; i++)
|
|
{
|
|
//get calculation pieces:
|
|
float seedMax = Mathf.Pow(10, _particles[i].randomSeed.ToString().Length);
|
|
float seedAsPercent = _particles[i].randomSeed / seedMax;
|
|
float travelPercentage = 1 - (_particles[i].remainingLifetime / _particles[i].startLifetime);
|
|
|
|
//bypass issue while running at edit time when particles haven't reached the spline end:
|
|
if (_spline.GetDirection(travelPercentage, false) == Vector3.zero) continue;
|
|
|
|
//get a direction off our current point on the path - rotating by 1080 results in better distribution since Unity's randomSeed for particles favors lower numbers:
|
|
Vector3 offshootDirection = Quaternion.AngleAxis(1080 * seedAsPercent, -_spline.GetDirection(travelPercentage, false)) * _spline.Up(travelPercentage);
|
|
Vector3 previousOffshootDirection = Quaternion.AngleAxis(1080 * seedAsPercent, -_spline.GetDirection(travelPercentage - _previousDiff, false)) * _spline.Up(travelPercentage - _previousDiff, false);
|
|
|
|
//cache our positions:
|
|
Vector3 position = _spline.GetPosition(travelPercentage, false);
|
|
|
|
//cache a previous position for velocity if possible:
|
|
Vector3 lastPosition = position;
|
|
if (travelPercentage - .01f >= 0) lastPosition = _spline.GetPosition(travelPercentage - _previousDiff, false);
|
|
|
|
//decide how far to offshoot from the spline based on where we are between the start and end radius:
|
|
float offset = Mathf.Lerp(startRadius, endRadius, travelPercentage);
|
|
float previousOffset = Mathf.Lerp(startRadius, endRadius, travelPercentage - _previousDiff);
|
|
|
|
//place particles depending on simulation space:
|
|
Vector3 currentPosition = Vector3.zero;
|
|
Vector3 previousPosition = Vector3.zero;
|
|
|
|
switch (_particleSystem.main.simulationSpace)
|
|
{
|
|
case ParticleSystemSimulationSpace.Local:
|
|
|
|
currentPosition = _particleSystem.transform.InverseTransformPoint(position + offshootDirection * offset);
|
|
previousPosition = _particleSystem.transform.InverseTransformPoint(lastPosition + previousOffshootDirection * previousOffset);
|
|
break;
|
|
|
|
case ParticleSystemSimulationSpace.World:
|
|
case ParticleSystemSimulationSpace.Custom:
|
|
currentPosition = position + offshootDirection * offset;
|
|
previousPosition = position + previousOffshootDirection * previousOffset;
|
|
break;
|
|
}
|
|
|
|
//apply:
|
|
_particles[i].position = currentPosition;
|
|
_particles[i].velocity = currentPosition - previousPosition;
|
|
}
|
|
|
|
//apply the particle changes back to the system:
|
|
_particleSystem.SetParticles (_particles, _particles.Length);
|
|
}
|
|
} |