using UnityEngine; using System; using System.Collections; using System.Collections.Generic; using PlaygroundSplines; namespace ParticlePlayground { [RequireComponent (typeof(ParticleSystem))] /// <summary> /// The PlaygroundParticlesC class is a Particle Playground system driven by the Playground Manager (PlaygroundC). A Particle Playground system contains settings and data for altering a Shuriken component. /// </summary> [ExecuteInEditMode()] public class PlaygroundParticlesC : MonoBehaviour { /************************************************************************************************************************************************* PlaygroundParticlesC variables *************************************************************************************************************************************************/ // Particle Playground settings /// <summary> /// The particle source method for distributing particles upon birth. /// </summary> [HideInInspector] public SOURCEC source; /// <summary> /// Current active state (when using state as source). /// </summary> [HideInInspector] public int activeState; /// <summary> /// If emission of particles is active on this PlaygroundParticles. /// </summary> [HideInInspector] public bool emit = true; /// <summary> /// Should a particle re-emit when reaching the end of its lifetime? /// </summary> [HideInInspector] public bool loop = true; /// <summary> /// Should particles be removed instantly when you set emit to false? /// </summary> [HideInInspector] public bool clearParticlesOnEmissionStop = false; /// <summary> /// Should the GameObject of this PlaygroundParticlesC disable when not looping? /// </summary> [HideInInspector] public bool disableOnDone = false; /// <summary> /// The routine that should run when particle simulation has ended. /// </summary> [HideInInspector] public ONDONE disableOnDoneRoutine; /// <summary> /// The rate to update this PlaygroundParticles. /// </summary> [HideInInspector] public int updateRate = 1; /// <summary> /// Determins if this particle system should calculate (can be overrided by PlaygroundC.calculate). This will automatically enable/disable when pauseCalculationWhenInvisible is set to true. /// </summary> [HideInInspector] public bool calculate = true; /// <summary> /// Calculate the delta movement force of this particle system. /// </summary> [HideInInspector] public bool calculateDeltaMovement = true; /// <summary> /// The strength to multiply delta movement with. /// </summary> [HideInInspector] public float deltaMovementStrength = 10f; /// <summary> /// The minimum strength to multiply delta movement with. This will apply when using deltaMovementStrengthValueMethod of RandomBetweenTwoValues. /// </summary> [HideInInspector] public float minDeltaMovementStrength = 0; [HideInInspector] public VALUEMETHOD deltaMovementStrengthValueMethod; /// <summary> /// The current world object will change its vertices over time. This produces memory garbage with quantity based upon the mesh vertices. /// </summary> [HideInInspector] public bool worldObjectUpdateVertices = false; /// <summary> /// The current world object will change its normals over time. This produces memory garbage with quantity based upon the mesh normals. /// </summary> [HideInInspector] public bool worldObjectUpdateNormals = false; /// <summary> /// The method to set the Lifetime Sorting: Nearest Neighbor/Reversed with. /// </summary> [HideInInspector] public NEARESTNEIGHBORORIGINMETHOD nearestNeighborOriginMethod; /// <summary> /// The initial source position when using lifetime sorting of Nearest Neighbor/Reversed and nearestNeighborOriginMethod of NEARESTNEIGHBORORIGINMETHOD.SourcePoint. /// This will let you sort the lifetime from a generated particle birth position. /// </summary> [HideInInspector] public int nearestNeighborOrigin = 0; /// <summary> /// The initial source position when using lifetime sorting of Nearest Neighbor/Reversed and nearestNeighborOriginMethod of NEARESTNEIGHBORORIGINMETHOD.Vector3. /// This will let you sort the lifetime from a Vector3 in world space. /// </summary> [HideInInspector] public Vector3 nearestNeighborOriginVector3; /// <summary> /// The initial source position when using lifetime sorting of Nearest Neighbor/Reversed and nearestNeighborOriginMethod of NEARESTNEIGHBORORIGINMETHOD.Transform. /// This will let you sort the lifetime from a Transform's position in world space. /// </summary> [HideInInspector] public Transform nearestNeighborOriginTransform; /// <summary> /// The amount of particles within this PlaygroundParticlesC object. /// </summary> [HideInInspector] public int particleCount; /// <summary> /// The percentage to emit of particleCount in bursts from this PlaygroundParticles. /// </summary> [HideInInspector] public float emissionRate = 1f; /// <summary> /// The method to calculate Overflow Offset with. /// </summary> [HideInInspector] public OVERFLOWMODEC overflowMode = OVERFLOWMODEC.SourceTransform; /// <summary> /// The offset direction and magnitude when particle count exceeds source count. /// </summary> [HideInInspector] public Vector3 overflowOffset; /// <summary> /// Should source position scattering be applied? /// </summary> [HideInInspector] public bool applySourceScatter = false; /// <summary> /// The minimum spread of source position scattering. /// </summary> [HideInInspector] public Vector3 sourceScatterMin; /// <summary> /// The maximum spread of source position scattering. /// </summary> [HideInInspector] public Vector3 sourceScatterMax; /// <summary> /// The scale of source scatter. This can be changed over time to move the scattering seamlessly. /// </summary> [HideInInspector] public Vector3 scatterScale = new Vector3(1f,1f,1f); [HideInInspector] public MINMAXVECTOR3METHOD sourceScatterMethod; /// <summary> /// Sort mode for particle lifetime. /// </summary> [HideInInspector] public SORTINGC sorting = SORTINGC.Scrambled; /// <summary> /// Custom sorting for particle lifetime (when sorting is set to Custom). /// </summary> [HideInInspector] public AnimationCurve lifetimeSorting; /// <summary> /// Minimum size of particles. /// </summary> [HideInInspector] public float sizeMin = 1f; /// <summary> /// Maximum size of particles. /// </summary> [HideInInspector] public float sizeMax = 1f; /// <summary> /// The scale of minimum and maximum particle size. /// </summary> [HideInInspector] public float scale = 1f; /// <summary> /// Minimum initial particle rotation. /// </summary> [HideInInspector] public float initialRotationMin; /// <summary> /// Maximum initial particle rotation. /// </summary> [HideInInspector] public float initialRotationMax; /// <summary> /// Minimum amount to rotate a particle over time. /// </summary> [HideInInspector] public float rotationSpeedMin; /// <summary> /// Maximum amount to rotate a particle over time. /// </summary> [HideInInspector] public float rotationSpeedMax; /// <summary> /// Should the particles rotate towards their movement direction. The rotationNormal will determine from which angle the rotation is based on. /// </summary> [HideInInspector] public bool rotateTowardsDirection = false; /// <summary> /// The rotation direction normal when rotating towards direction (always normalized value). /// </summary> [HideInInspector] public Vector3 rotationNormal = -Vector3.forward; /// <summary> /// The method to apply lifetime values. /// </summary> [HideInInspector] public VALUEMETHOD lifetimeValueMethod; /// <summary> /// The maximum life of a particle in seconds. /// </summary> [HideInInspector] public float lifetime; /// <summary> /// The minimum life of a particle when using lifetimeValueMethod of RandomBetweenTwoValues. /// </summary> [HideInInspector] public float lifetimeMin = 0; /// <summary> /// The offset of lifetime in this particle system. /// </summary> [HideInInspector] public float lifetimeOffset; /// <summary> /// The emission during lifetime. This will compress the Lifetime Sorting pattern over the total lifetime. /// This can be used to have particles live longer than the otherwise obvious repeating pattern. /// </summary> [HideInInspector] public float lifetimeEmission = 1f; /// <summary> /// The minimum Shuriken lifetime clamps the lifetime value for each particle. /// When a Shuriken particle reaches 0 it will result in being removed from screen, where a noticable flicker will occur if the particle has the same birth as death position. /// Upon using Texture Sheet Animation you may want this to be set to 0 if your particles has a short lifetime (below 1) to get all tiles into the animation. /// </summary> [HideInInspector] public float minShurikenLifetime = .08f; /// <summary> /// Should lifetime size affect each particle? /// </summary> [HideInInspector] public bool applyLifetimeSize = true; /// <summary> /// The size over lifetime of each particle. /// </summary> [HideInInspector] public AnimationCurve lifetimeSize; /// <summary> /// Should particle array size affect each particle? This will multiply the size of each particle depending on its position in the particle array. /// </summary> [HideInInspector] public bool applyParticleArraySize; /// <summary> /// The size over particle array of each particle. This will multiply the size of each particle depending on its position in the particle array. /// </summary> [HideInInspector] public AnimationCurve particleArraySize; /// <summary> /// Should the particles transition back to their source position during their lifetime? Use transitionBackToSourceAmount to set the strength by a normalized AnimationCurve. /// </summary> [HideInInspector] public bool transitionBackToSource = false; /// <summary> /// The amount to transition back to the source position by a normalized AnimationCurve. /// </summary> [HideInInspector] public AnimationCurve transitionBackToSourceAmount; /// <summary> /// Should the particles only position on their source (and not apply any forces)? /// </summary> [HideInInspector] public bool onlySourcePositioning = false; /// <summary> /// Should the particles only position by lifetime positioning Vector3AnimationCurves? /// </summary> [HideInInspector] public bool onlyLifetimePositioning = false; /// <summary> /// The lifetime positioning of particles using a Vector3AnimationCurveC. This will annihilate any forces and only move particles on the X, Y and Z Animation Curves. /// </summary> [HideInInspector] public Vector3AnimationCurveC lifetimePositioning; /// <summary> /// Should scale over time of lifetime positioning apply? /// </summary> [HideInInspector] public bool applyLifetimePositioningTimeScale = false; /// <summary> /// Should scale of position of lifetime positioning apply? /// </summary> [HideInInspector] public bool applyLifetimePositioningPositionScale = false; /// <summary> /// The scale of time for lifetime positioning. /// </summary> [HideInInspector] public AnimationCurve lifetimePositioningTimeScale; /// <summary> /// The scale of positioning for lifetime positioning. /// </summary> [HideInInspector] public AnimationCurve lifetimePositioningPositionScale; /// <summary> /// The overall scale of lifetime positioning. /// </summary> [HideInInspector] public float lifetimePositioningScale = 1f; /// <summary> /// Should lifetime positioning use the direction normal of the source? /// </summary> [HideInInspector] public bool lifetimePositioningUsesSourceDirection = false; /// <summary> /// Should lifetime velocity affect particles? /// </summary> [HideInInspector] public bool applyLifetimeVelocity = false; /// <summary> /// The velocity over lifetime of each particle. /// </summary> [HideInInspector] public Vector3AnimationCurveC lifetimeVelocity; /// <summary> /// The lifetime velocity scale. /// </summary> [HideInInspector] public float lifetimeVelocityScale = 1f; /// <summary> /// Should initial velocity affect particles? /// </summary> [HideInInspector] public bool applyInitialVelocity = false; /// <summary> /// The minimum starting velocity of each particle. /// </summary> [HideInInspector] public Vector3 initialVelocityMin; /// <summary> /// The maximum starting velocity of each particle. /// </summary> [HideInInspector] public Vector3 initialVelocityMax; /// <summary> /// Determines if the value of initial velocity should be rectangular or spherical. /// </summary> [HideInInspector] public MINMAXVECTOR3METHOD initialVelocityMethod; /// <summary> /// Should initial local velocity affect particles? /// </summary> [HideInInspector] public bool applyInitialLocalVelocity = false; /// <summary> /// The minimum starting velocity of each particle with normal or transform direction. /// </summary> [HideInInspector] public Vector3 initialLocalVelocityMin; /// <summary> /// The maximum starting velocity of each particle with normal or transform direction. /// </summary> [HideInInspector] public Vector3 initialLocalVelocityMax; /// <summary> /// Determines if the value of initial local velocity should be rectangular or spherical. /// </summary> [HideInInspector] public MINMAXVECTOR3METHOD initialLocalVelocityMethod; /// <summary> /// Should the initial velocity shape be applied on particle re/birth? /// </summary> [HideInInspector] public bool applyInitialVelocityShape = false; /// <summary> /// The amount of velocity to apply of the spawning particle's initial/local velocity in form of a Vector3AnimationCurve. /// </summary> [HideInInspector] public Vector3AnimationCurveC initialVelocityShape; /// <summary> /// The scale of initial velocity shape. /// </summary> [HideInInspector] public float initialVelocityShapeScale = 1f; /// <summary> /// Should bending affect particles velocity? /// </summary> [HideInInspector] public bool applyVelocityBending; /// <summary> /// The amount to bend velocity of each particle. /// </summary> [HideInInspector] public Vector3 velocityBending; /// <summary> /// The type of velocity bending. /// </summary> [HideInInspector] public VELOCITYBENDINGTYPEC velocityBendingType; /// <summary> /// The constant force towards gravitational vector. /// </summary> [HideInInspector] public Vector3 gravity; /// <summary> /// The maximum positive- and negative velocity of each particle. /// </summary> [HideInInspector] public float maxVelocity = 100f; /// <summary> /// The force axis constraints of each particle. /// </summary> [HideInInspector] public PlaygroundAxisConstraintsC axisConstraints = new PlaygroundAxisConstraintsC(); /// <summary> /// Particles inertia over time. /// </summary> [HideInInspector] public float damping; /// <summary> /// The overall scale of velocity. /// </summary> [HideInInspector] public float velocityScale = 1f; /// <summary> /// The color over lifetime. /// </summary> [HideInInspector] public Gradient lifetimeColor; /// <summary> /// The colors over lifetime (if Color Source is set to LifetimeColors). /// </summary> [HideInInspector] public List<PlaygroundGradientC> lifetimeColors = new List<PlaygroundGradientC>(); /// <summary> /// The source to read color from (fallback on Lifetime Color if no source color is available). /// </summary> [HideInInspector] public COLORSOURCEC colorSource = COLORSOURCEC.Source; /// <summary> /// Should the source color use alpha from Lifetime Color instead of the source's original alpha? /// </summary> [HideInInspector] public bool sourceUsesLifetimeAlpha; /// <summary> /// The method to color particles with. Either evaluated by their lifetime or by their position in the ParticleCache array. /// </summary> [HideInInspector] public COLORMETHOD colorMethod; /// <summary> /// Determines if particles should get a secondary alpha applied from the arrayColorAlpha gradient when using colorMethod of COLORMETHOD.ParticleArray. /// </summary> [HideInInspector] public bool arrayColorUsesAlpha; /// <summary> /// The array color alpha. /// </summary> [HideInInspector] public Gradient arrayColorAlpha; /// <summary> /// Should the movement of the particle system transform when in local simulation space be compensated for? /// </summary> [HideInInspector] public bool applyLocalSpaceMovementCompensation = true; /// <summary> /// Should particles get a new random size upon rebirth? /// </summary> [HideInInspector] public bool applyRandomSizeOnRebirth = true; /// <summary> /// Should particles get a new random velocity upon rebirth? /// </summary> [HideInInspector] public bool applyRandomInitialVelocityOnRebirth = true; /// <summary> /// Should particles get a new random rotation upon rebirth? /// </summary> [HideInInspector] public bool applyRandomRotationOnRebirth = true; /// <summary> /// Should particles get a new scatter position upon rebirth? /// </summary> [HideInInspector] public bool applyRandomScatterOnRebirth = false; /// <summary> /// Should particles get their initial calculated color upon rebirth? (Can resolve flickering upon rebirth.) /// </summary> [HideInInspector] public bool applyInitialColorOnRebirth = false; /// <summary> /// Should particles get a new random lifetime upon rebirth? /// </summary> [HideInInspector] public bool applyRandomLifetimeOnRebirth = true; /// <summary> /// Should particle birth position be adjusted with the delta time from birth to current? This will make the particles appear linearly. /// </summary> [HideInInspector] public bool applyDeltaOnRebirth = true; /// <summary> /// Should each birthing particle calculate the local manipulators immediately? /// </summary> [HideInInspector] public bool calculateManipulatorOnRebirth = false; /// <summary> /// Should the particle system pause calculation upon becoming invisible? /// </summary> [HideInInspector] public bool pauseCalculationWhenInvisible = false; /// <summary> /// Should the calculation trigger size gizmo be visible in Scene View? /// </summary> [HideInInspector] public bool calculationTriggerSizeGizmo = false; /// <summary> /// The calculation trigger transform determines the origin of the rendered particle area. This will affect the calculation trigger when pauseCalculationWhenInvisible is set to true. /// </summary> [HideInInspector] public Transform calculationTriggerTransform; /// <summary> /// The calculation trigger size determines the size of the rendered particle area. This will affect the calculation trigger when pauseCalculationWhenInvisible is set to true. /// </summary> [HideInInspector] public Vector3 calculationTriggerSize = new Vector3(1f,1f,1f); /// <summary> /// The calculation trigger offset determines the offset from the calculationTriggerTransform position. This will affect the calculation trigger when pauseCalculationWhenInvisible is set to true. /// </summary> [HideInInspector] public Vector3 calculationTriggerOffset = new Vector3(); /// <summary> /// Should the particle system force Play() when GameObject is outside of camera view? (Fix for Shuriken stop rendering.) /// </summary> [HideInInspector] public bool forceVisibilityWhenOutOfFrustrum = true; /// <summary> /// Should each particle's position be synced with main-threaad? Use this when dealing with moving source objects or if you experience a laggy particle movement. /// </summary> [HideInInspector] public bool syncPositionsOnMainThread = false; /// <summary> /// Should the particle system force itself to remain in lockPosition? /// </summary> [HideInInspector] public bool applyLockPosition = false; /// <summary> /// Should the particle system force itself to remain in lockRotation? /// </summary> [HideInInspector] public bool applyLockRotation = false; /// <summary> /// Should the particle system force itself to remain in lockScale? /// </summary> [HideInInspector] public bool applyLockScale = false; /// <summary> /// The locked position is considered local. /// </summary> [HideInInspector] public bool lockPositionIsLocal = false; /// <summary> /// The locked rotation is considered local. /// </summary> [HideInInspector] public bool lockRotationIsLocal = false; /// <summary> /// The locked position. /// </summary> [HideInInspector] public Vector3 lockPosition = Vector3.zero; /// <summary> /// The locked rotation. /// </summary> [HideInInspector] public Vector3 lockRotation = Vector3.zero; /// <summary> /// The locked scale. /// </summary> [HideInInspector] public Vector3 lockScale = new Vector3(1f,1f,1f); /// <summary> /// Should the movementCompensationLifetimeStrength affect local space movement compensation? /// </summary> [HideInInspector] public bool applyMovementCompensationLifetimeStrength = false; /// <summary> /// The strength of movement compensation over particles lifetime /// </summary> [HideInInspector] public AnimationCurve movementCompensationLifetimeStrength; /// <summary> /// Determines if masking should be applied to the particles. /// </summary> [HideInInspector] public bool applyParticleMask; /// <summary> /// The masked amount of particles. The particleMaskTime will determine if the particles should fade in/out. /// </summary> [HideInInspector] public int particleMask = 0; /// <summary> /// The time it takes to mask in/out particles when using particleMask. /// </summary> [HideInInspector] public float particleMaskTime = 0f; /// <summary> /// The method to distribute the sorting mask when particleMask is above 0. /// </summary> [HideInInspector] public MASKSORTINGC particleMaskSorting; /// <summary> /// The speed of stretching to reach full effect. /// </summary> [HideInInspector] public float stretchSpeed = 1f; /// <summary> /// Should the start direction of particle stretching be applied? /// </summary> [HideInInspector] public bool applyStretchStartDirection = false; /// <summary> /// The starting direction of stretching if all initial velocity is zero. /// </summary> [HideInInspector] public Vector3 stretchStartDirection = Vector3.zero; /// <summary> /// Should lifetime stretching be applied? /// </summary> [HideInInspector] public bool applyLifetimeStretching = false; /// <summary> /// The lifetime stretching of stretched particles. /// </summary> [HideInInspector] public AnimationCurve stretchLifetime; /// <summary> /// The multithreading method how this particle system should calculate. Use this to bypass the Playground Manager's threadMethod. /// </summary> [HideInInspector] public ThreadMethodLocal threadMethod; /// <summary> /// Determines if multithreading should be used to initialize all caches for the particle system. /// The tradeoff of sparing the main thread from initializing all caches is that it can result in the particle system taking a couple of frames before it's ready to start emission. /// </summary> [HideInInspector] public bool multithreadedStartup = true; // Source Script variables /// <summary> /// When using Emit() the index will point to the next particle in pool to emit. /// </summary> [HideInInspector] public int scriptedEmissionIndex; /// <summary> /// When using Emit() the passed in position will determine the position for this particle. /// </summary> [HideInInspector] public Vector3 scriptedEmissionPosition; /// <summary> /// When using Emit() the passed in velocity will determine the speed and direction for this particle. /// </summary> [HideInInspector] public Vector3 scriptedEmissionVelocity; /// <summary> /// When using Emit() the passed in color will decide the color for this particle if colorSource is set to COLORSOURCEC.Source. /// </summary> [HideInInspector] public Color scriptedEmissionColor = Color.white; /// <summary> /// When using Emit() the passed in scriptedLifetime will determine the lifetime of the particle. /// </summary> [HideInInspector] float scriptedLifetime = 0; // Collision detection /// <summary> /// Determines if particles can collide. Enable this if you want particles to continuously look for colliders of type collisionType (2D/3D). Particle collision will run on main-thread. /// </summary> [HideInInspector] public bool collision = false; /// <summary> /// Should particles affect rigidbodies? The mass determines how much they will affect the rigidobdy. /// </summary> [HideInInspector] public bool affectRigidbodies = true; [HideInInspector] public bool inverseRigidbodyCollision = false; /// <summary> /// The mass of a particle (calculated in collision with rigidbodies). /// </summary> [HideInInspector] public float mass = .01f; /// <summary> /// The spherical radius of a particle used upon collision. /// </summary> [HideInInspector] public float collisionRadius = 1f; /// <summary> /// The layers these particles will collide with. /// </summary> [HideInInspector] public LayerMask collisionMask; [HideInInspector] public List<Transform> collisionExclusion; /// <summary> /// The amount a particle will loose of its lifetime on collision. /// </summary> [HideInInspector] public float lifetimeLoss = 0f; /// <summary> /// The amount a particle will bounce on collision. /// </summary> [HideInInspector] public float bounciness = .5f; /// <summary> /// The minimum amount of random bounciness (seen as negative offset from the collided surface's normal direction). /// </summary> [HideInInspector] public Vector3 bounceRandomMin; /// <summary> /// The maximum amount of random bounciness (seen as positive offset from the collided surface's normal direction). /// </summary> [HideInInspector] public Vector3 bounceRandomMax; /// <summary> /// The Playground Colliders of this particle system. A Playground Collider is an infinite collision plane based on a Transform in the scene. /// </summary> [HideInInspector] public List<PlaygroundColliderC> colliders; /// <summary> /// The type of collision. This determines if 2D- or 3D raycasting should be used. /// </summary> [HideInInspector] public COLLISIONTYPEC collisionType; /// <summary> /// Minimum collision depth of Raycast2D. /// </summary> [HideInInspector] public float minCollisionDepth = 0f; /// <summary> /// Maximum collision depth of Raycast2D. /// </summary> [HideInInspector] public float maxCollisionDepth = 0f; /// <summary> /// Determines if particles should stick to their collided surface. /// </summary> [HideInInspector] public bool stickyCollisions = false; /// <summary> /// The sticky collisions offset from the collided surface normal. /// </summary> [HideInInspector] public float stickyCollisionsSurfaceOffset = 0; [HideInInspector] public LayerMask stickyCollisionsMask = -1; /// <summary> /// Determines if collisions should be calculated using Vector3.Distance (if set to true) or Vector3.SqrMagnitude (if set to false). /// </summary> [HideInInspector] public bool collisionPrecision = false; /// <summary> /// Determines if collisions should be cached even if stickyCollisions isn't set to true. Enable this if you want to extend your scripts upon the collision information for the particles when not using sticky collisions. /// Having this disabled will minimize transform component lookups during collisions. /// </summary> [HideInInspector] public bool forceCollisionCaching = false; [HideInInspector] public bool maskedParticlesBypassCollision = true; // States (source) /// <summary> /// The list of States for this PlaygroundParticles. A State is Source data from a texture or mesh which determines where particles will be positioned upon birth. /// </summary> public List<ParticleStateC> states = new List<ParticleStateC>(); // Splines /// <summary> /// The splines used as Source. Particle birth positions will populate along the spline using the list of particles as normalized time on the curves of the spline. To offset the time use splineTimeOffset. /// </summary> [HideInInspector] public List<PlaygroundSpline> splines; [HideInInspector] public float splineTimeOffset; [HideInInspector] public bool treatAsOneSpline; int splineIndex = 0; // Scene objects (source) /// <summary> /// A mesh as source calculated within the scene. /// </summary> [HideInInspector] public WorldObject worldObject = new WorldObject(); /// <summary> /// A skinned mesh as source calculated within the scene. /// </summary> [HideInInspector] public SkinnedWorldObject skinnedWorldObject = new SkinnedWorldObject(); [HideInInspector] public bool forceSkinnedMeshUpdateOnMainThread = false; /// <summary> /// A transform calculated within the scene. /// </summary> [HideInInspector] public Transform sourceTransform; [HideInInspector] public List<PlaygroundTransformC> sourceTransforms; [HideInInspector] public bool treatAsOneTransform; int transformIndex = 0; [HideInInspector] public PlaygroundParticlesC otherParticleSource; [HideInInspector] public SOURCEBIRTHMETHOD otherParticleSourceMethod; // Paint /// <summary> /// The paint source of this PlaygroundParticles. /// </summary> [HideInInspector] public PaintObjectC paint; // Projection /// <summary> /// The projection source of this PlaygroundParticles. /// </summary> [HideInInspector] public ParticleProjectionC projection; // Manipulators /// <summary> /// The list of Local Manipulator Objects handled by this PlaygroundParticlesC object. /// </summary> public List<ManipulatorObjectC> manipulators; // Events /// <summary> /// List of event objects handled by this PlaygroundParticlesC object. /// </summary> [HideInInspector] public List<PlaygroundEventC> events; // Cache /// <summary> /// Data for each particle. /// </summary> [NonSerialized] public PlaygroundCache playgroundCache = new PlaygroundCache(); /// <summary> /// The particle pool. /// </summary> [NonSerialized] public ParticleSystem.Particle[] particleCache; [NonSerialized] public CollisionCache collisionCache; // Snapshots /// <summary> /// Saved data of properties (positions, velocities, colors etc.). /// </summary> [HideInInspector] public List<PlaygroundSave> snapshots = new List<PlaygroundSave>(); /// <summary> /// Should the particle system load stored data from start? /// </summary> [HideInInspector] public bool loadFromStart = false; /// <summary> /// Which data should be loaded (if loadFromStart is true). /// </summary> [HideInInspector] public int loadFrom = 0; /// <summary> /// Should a transition occur whenever a Load is issued? /// </summary> [HideInInspector] public bool loadTransition = false; /// <summary> /// The type of transition to occur whenever a Load is issued. /// </summary> [HideInInspector] public TRANSITIONTYPEC loadTransitionType; /// <summary> /// The time for load transition in seconds. /// </summary> [HideInInspector] public float loadTransitionTime = 1f; /// <summary> /// The storage of position data if this is a snapshot. /// </summary> [HideInInspector] public PlaygroundCache snapshotData; /// <summary> /// The global time the snapshot was made. /// </summary> [HideInInspector] public float timeOfSnapshot = 0; /// <summary> /// Is this particle system a snapshot? /// </summary> public bool isSnapshot = false; // Components /// <summary> /// This ParticleSystem (Shuriken) component. /// </summary> [HideInInspector] public ParticleSystem shurikenParticleSystem; /// <summary> /// The id of this PlaygroundParticlesC object. /// </summary> [HideInInspector] public int particleSystemId; /// <summary> /// The GameObject of a PlaygroundParticlesC object. /// </summary> [HideInInspector] public GameObject particleSystemGameObject; /// <summary> /// The Transform of a PlaygroundParticlesC object. /// </summary> [HideInInspector] public Transform particleSystemTransform; /// <summary> /// The Renderer of a PlaygroundParticlesC object. /// </summary> [HideInInspector] public Renderer particleSystemRenderer; /// <summary> /// The ParticleSystemRenderer of a PlaygroundParticlesC object. /// </summary> [HideInInspector] public ParticleSystemRenderer particleSystemRenderer2; /// <summary> /// The PlaygroundParticlesC that is controlling this particle system. /// </summary> [HideInInspector] public List<PlaygroundParticlesC> eventControlledBy = new List<PlaygroundParticlesC>(); // Turbulence /// <summary> /// The Simplex Turbulence object. /// </summary> SimplexNoise turbulenceSimplex; /// <summary> /// The type of turbulence. /// </summary> [HideInInspector] public TURBULENCETYPE turbulenceType = TURBULENCETYPE.None; /// <summary> /// The turbulence strength. /// </summary> [HideInInspector] public float turbulenceStrength = 10f; /// <summary> /// The turbulence resolution scale. A higher value will generate a more dense grid. /// </summary> [HideInInspector] public float turbulenceScale = 1f; /// <summary> /// The turbulence time scale. /// </summary> [HideInInspector] public float turbulenceTimeScale = 1f; /// <summary> /// Should Turbulence Lifetime Strength apply? /// </summary> [HideInInspector] public bool turbulenceApplyLifetimeStrength = false; /// <summary> /// The Turbulence Lifetime Strength. Use this to control how much turbulence will affect the particle over its lifetime. /// </summary> [HideInInspector] public AnimationCurve turbulenceLifetimeStrength; [HideInInspector] public bool prewarm = false; [HideInInspector] public float prewarmTime = 1f; [HideInInspector] public int prewarmCycles = 16; /// <summary> /// The simulation time scale for all particles within this system. Set time scale to 0 to pause a particle system. /// </summary> [HideInInspector] public float particleTimescale = 1f;
Source
It all starts here, the Source determines from which position particles will emit within the scene. Every Source ranging from Transforms,
Meshes, Textures, Paint and Projections has different settings and approaches for how to structure Source Positions within the scene.
State
Emit from pre-defined positions created from an image or mesh. All Particle Playground systems uses a list of states to store data from
a mesh’s vertices or an image’s pixels. When creating a new State from an image you can define Texture, Depthamp (with Depthmap
Strength), Name, Scale, Offset and a parent Transform. When creating a State from a mesh you can define Mesh, Texture, Name, Scale,
Offset and Transform. Using a Transform will make you able to position, rotate and scale the State.
Name
The name of this State.
Texture
Takes a Texture2D which will structure the State in color and positions from the Texture2D’s pixels. If you use a texture when
creating the State from a mesh, the positions will be colored from the UV-mapping of the mesh.
Depthmap
Takes a Texture2D which will define the Z-value in normalized value by grayscale. A black pixel is 0.0 and a white is 1.0.
Depthmap Strength
The amount the Depthmap will multiply the Z-positioning. A Depthmap Strength of 1.0 will affect the Z-positions one Unit
ranging from black to white.
Mesh
The mesh to construct your State from. Each vertex in the mesh will define a position in the State.
Transform
To be able to position, rotate and scale a State you will need a Transform assigned from the scene.
Scale
The world scale of this State. Each pixel will originally be a square of 1×1 Units. To make the final size of a State smaller, use a
number below 1.0. Using a number below 0 will invert the State in X- and Y positions.
Offset
A State will be created in Vector3(0, 0, 0) in world coordinates (or local coordinates if a stateTransform is set) with origin of the
image’s bottom left or a mesh’s pivot. Use the offset to place it elsewhere, with offset from world’s or stateTransform’s Vector3(0,
0, 0) measured in Units.
Chroma Key
Filters out a specific color within Spread range. This is useful if the State’s texture doesn’t have any alpha information.
Transform
Emit from one or several Transform components within your scene.
Treat As One Transform
Determines the birth distribution of particles over the assigned transforms.
World Object
Emit from a Mesh component within your scene.
Mesh Vertices Update
Enable this if the World Object’s mesh is procedural and changes vertices over time.
Mesh Normals Update
Enable this if the World Object’s mesh is procedural and changes normals over time.
Skinned World Object
Emit from a Skinned Mesh component within your scene.
Force Update On Main-Thread
Enable Main-Thread updating to ensure correct birth positions on the live vertices. This can have a noticeable impact on
performance as the skinned mesh vertex extraction won’t be multithreaded.
Mesh Vertices Update
Enable this if the Skinned World Object’s mesh is procedural and changes vertices over time.
Mesh Normals Update
Enable this if the Skinned World Object’s mesh is procedural and changes normals over time.
Source Down Resolution
The source vertex skipping. Use this to lower the distribution of particles needed along your complete skinned mesh. Each
position will be determined by jumping over vertices in the vertex list. The amount of calculated positions will be divided by how
many positions you’ve decided to skip. This is in many cases needed to amp performance when using skinned meshes in your
scene, especially when you target mobile platforms.
Script
Control all particle emission behavior through custom scripts (advanced). Use PlaygroundParticlesC.Emit(position, velocity, color) to
create a particle at position. Several overloads are available where you also can emit a number of particles instantly. Please see the Ink
example scene for basic usage. Through the Inspector you’re presented with some basic control to try emission before putting them
into a script call,
Emission Index
The particle’s array position that will emit when you call Emit() on this PlaygroundParticlesC object.
Position
The particle’s initial emission position when you call Emit() on this PlaygroundParticlesC object.
Velocity
The velocity of the particle that will emit when you call Emit() on this PlaygroundParticlesC object.
Color
The color of the particle that will emit when you call Emit() on this PlaygroundParticlesC object.
Paint
Paint positions and color by using your own brushes, or by a single point with color information. Creating your own brushes can be
done through the Brush Wizard, which you’ll find in the Brush Preset menu when selecting Brush as Paint Mode. All painting features
relies on colliders being hit in the scene. To paint live into the scene in script please see the example script PaintAtMousePositionC.
Paint Mode
This is an Editor-specific feature which lets you switch between painting with a single point (Dot), using predefined brushes (Brush)
or erasing paint positions (Eraser).
Brushes
Painting with brushes lets you fill a larger area with a predefined texture rather than a single point (like Paint Mode: Dot). You can
define the texture yourself along with how the brush should function, such as detail, scale and spacing. When painting, each pixel
(depending on chosen Detail level) will represent a ray into the scene at screen position. Each ray need to hit a collider to create a
Paint Position at world point.
b
A list of predefined brushes with specific settings which will define current paint settings upon selection. You can create your
own presets by pressing the ”Create”-button which will open the Brush Wizard. A preset is stored in Particle Playground/
Resources/Brushes and can be edited through the Inspector. To remove a preset from the Brush Preset list either delete the
prefab in the ”Brushes”-folder or change the presentation mode to ”List” instead of ”Icons” and press the button ”-”.
Brush Shape
The texture to project onto the surface where you choose to paint. The texture’s amount of pixels (width and height) will be
calculated for the amount of Paint Positions that will be created (amount is shown in the ”Paint” progress bar). All brush
textures need to have Read/Write Enabled and use True Color (non-compressed) in their Import Settings.
Brush Detail
The detail represents how many of the original pixels that should be read from the Brush Shape texture. This will affect how
many positions that will be created on every brush stroke. Keep in mind that it’s by rare occasions you ever need a perfect
copy of your brush’s full pixel amount onto a surface.
Perfect
Every pixel will be read (100% of existing texture pixels).
High
Every second pixel will be read (50% of existing texture pixels).
Medium
Every forth pixel will be read (25% of existing texture pixels).
Low
Every sixth pixel will be read (16.6% of existing texture pixels).
Brush Scale
The scale of a brush measured by the ratio of the original Brush Shape texture. For instance, a texture with 32×32 pixels and
a scale of 0.5 will represent a screen space area of 16×16 pixels.
Brush Distance
How far the brush sees from its origin position into the scene (in the Editor the origin is the Scene View’s camera). If the
distance is shorter than the target collider you want to paint on then no Paint Positions will be created.
Use Brush Color
Each Paint Position is created along with the Brush Shape’s color information at the ray’s pixel coordinate. Disabling this will
use the Color chosen by you instead, the alpha information will still be used from the Brush Shape texture.
Color
The color to paint with when using the Dot Paint Mode. If you disable ”Use Brush Color” for a brush then Color will determine each
Paint Position color instead.
Paint Mask
Determines which layer of colliders the paint function sees in the scene. Available for all Paint Modes (Dot, Brush and Eraser). Use
this to see through certain objects or mask out a single object in the scene to avoid spilling paint.
Paint Spacing
The space needed for next paint position to occur. This is measured from the last paint position’s world point towards where next
will end up while painting. A transparent green disc will show the spacing area in Scene View while painting. Use this to distribute
paint more evenly along a surface for instance.
Max Paint Positions
The max positions allowed to be stored by this Paint object. Use this to limit the existing Paint Positions within a scene. Exceed Max
Stops Paint will determine if no more painting can occur or if Paint Positions will be removed (ascending from first position in list)
when reaching the max limit.
Paint – Inspector information
The amount of Paint Positions currently in the scene. ”Max Paint Positions” will determine where 100% of the progress bar is. If you
suddenly can’t see all Paint Positions the reason is much likely that you need to extend the Particle Count in Particle Settings.
Start/Stop Paint
Use this to begin or abort painting into the scene.
Clear
Removes all Paint Positions from the scene.
Projection
Project particles from a transform using a texture. This behaves similarly to the Unity Projector. This can be used to for instance create
fog, dust or splashes on certain surfaces. Choose to offset the origin texture and the projected source position from the surface using
the projected normal’s direction. Use Live Update to update the projection position every frame. You can scale your projection in any
direction with the projection transform.
Projection Texture
The image to use where each pixel will wander through the scene in form of a Raycast.
Transform
The transform to project from.
Live Update
Determines if the projection should update every frame. Enable this if your projection transform moves or you have projected
objects moving inside the projection area.
Origin Offset
Offset the texture’s origin in X- and Y values.
Projection Distance
Determines how far the projection rays can travel into the scene, measured in Units.
Projection Scale
The scale of projection in Units. A scale of one will make each pixel one Unit. When using local simulation space, use this to scale
rather than the projection transform to ensure correct projection depth.
Surface Offset
Determines how far away the source position will be distributed from surface. Using the projected surface normal.
Projection Mask
The layer mask of which colliders within layer can be seen by the projection rays in the scene.
Spline
Emit particles from one or several Playground Splines in the scene. A Playground Spline is multithreading friendly and can be updated
live during runtime. Each node and bezier handle can be set towards a Transform, for easier live manipulation.
Time Offset
The offset of the spline’s curves. This can be used to move particles over time on the spline.
Treat As One Spline
Determines the birth distribution of particles over the assigned splines.