// Rebirth of a specified particle
		public static void Rebirth (PlaygroundParticlesC playgroundParticles, int p, System.Random random) {
			if (!playgroundParticles.hasActiveParticles) return;
			
			// Set initial values
			playgroundParticles.playgroundCache.rebirth[p] = playgroundParticles.source==SOURCEC.Script?true:(playgroundParticles.emit && (playgroundParticles.loop || playgroundParticles.playgroundCache.isNonBirthed[p]) && playgroundParticles.playgroundCache.emission[p]);
			playgroundParticles.playgroundCache.isFirstLoop[p] = playgroundParticles.playgroundCache.isNonBirthed[p];
			playgroundParticles.playgroundCache.isNonBirthed[p] = false;
			playgroundParticles.playgroundCache.life[p] = 0f;
			playgroundParticles.playgroundCache.birth[p] = playgroundParticles.playgroundCache.death[p];
			playgroundParticles.playgroundCache.death[p] += playgroundParticles.lifetime;
			playgroundParticles.playgroundCache.velocity[p] = Vector3.zero;
			playgroundParticles.playgroundCache.noForce[p] = false;
			
			if (playgroundParticles.hasCollisionCache)
				playgroundParticles.collisionCache.Reset(p);
			
			// Reset manipulators influence
			playgroundParticles.playgroundCache.changedByProperty[p] = false;
			playgroundParticles.playgroundCache.changedByPropertyColor[p] = false;
			playgroundParticles.playgroundCache.changedByPropertyColorLerp[p] = false;
			playgroundParticles.playgroundCache.changedByPropertyColorKeepAlpha[p] = false;
			playgroundParticles.playgroundCache.changedByPropertySize[p] = false;
			playgroundParticles.playgroundCache.changedByPropertyTarget[p] = false;
			playgroundParticles.playgroundCache.changedByPropertyDeath[p] = false;
			playgroundParticles.playgroundCache.propertyTarget[p] = 0;
			playgroundParticles.playgroundCache.propertyId[p] = 0;
			playgroundParticles.playgroundCache.propertyColorId[p] = 0;
			playgroundParticles.playgroundCache.manipulatorId[p] = 0;
			
			// Set new random size
			if (playgroundParticles.applyRandomSizeOnRebirth)
				playgroundParticles.playgroundCache.initialSize[p] = RandomRange(random, playgroundParticles.sizeMin, playgroundParticles.sizeMax);
			
			// Initial velocity
			if (!playgroundParticles.onlySourcePositioning && !playgroundParticles.onlyLifetimePositioning) {
				
				// Initial global velocity
				if (playgroundParticles.applyInitialVelocity) {
					if (playgroundParticles.applyRandomInitialVelocityOnRebirth) {
						if (playgroundParticles.initialVelocityMethod==MINMAXVECTOR3METHOD.Spherical)
							playgroundParticles.playgroundCache.initialVelocity[p] = RandomRangeSpherical(random, playgroundParticles.initialVelocityMin.x, playgroundParticles.initialVelocityMax.x);
						else if (playgroundParticles.initialVelocityMethod==MINMAXVECTOR3METHOD.SphericalLinear)
							playgroundParticles.playgroundCache.initialVelocity[p] = RandomRangeSpherical(random, playgroundParticles.initialVelocityMin.x, playgroundParticles.initialVelocityMax.x, (p*1f)/(playgroundParticles.particleCount*1f));
						else if (playgroundParticles.initialVelocityMethod==MINMAXVECTOR3METHOD.RectangularLinear)
							playgroundParticles.playgroundCache.initialVelocity[p] = Vector3.Lerp (playgroundParticles.initialVelocityMin, playgroundParticles.initialVelocityMax, (p*1f)/(playgroundParticles.particleCount*1f));
						//else if (playgroundParticles.initialVelocityMethod==MINMAXVECTOR3METHOD.SphericalSector)
						//	playgroundParticles.playgroundCache.initialVelocity[p] = RandomRangeSpherical(random, playgroundParticles.initialVelocityMin.x, playgroundParticles.initialVelocityMax.x, playgroundParticles.initialVelocityMin.y, playgroundParticles.initialVelocityMax.y);
						//else if (playgroundParticles.initialVelocityMethod==MINMAXVECTOR3METHOD.SphericalSectorLinear)
						//	playgroundParticles.playgroundCache.initialVelocity[p] = RandomRangeSpherical(random, playgroundParticles.initialVelocityMin.x, playgroundParticles.initialVelocityMax.x, playgroundParticles.initialVelocityMin.y, playgroundParticles.initialVelocityMax.y, (p*1f)/(playgroundParticles.particleCount*1f));
						else playgroundParticles.playgroundCache.initialVelocity[p] = RandomRange(random, playgroundParticles.initialVelocityMin, playgroundParticles.initialVelocityMax);
					}
					playgroundParticles.playgroundCache.velocity[p] = playgroundParticles.playgroundCache.initialVelocity[p];
					
					// Give this spawning particle its velocity shape
					if (playgroundParticles.applyInitialVelocityShape)
						playgroundParticles.playgroundCache.velocity[p] = Vector3.Scale(playgroundParticles.playgroundCache.velocity[p], playgroundParticles.initialVelocityShape.Evaluate((p*1f)/(playgroundParticles.particleCount*1f), playgroundParticles.initialVelocityShapeScale));
				}
				
				// Initial local velocity
				if (playgroundParticles.applyInitialLocalVelocity && playgroundParticles.source!=SOURCEC.Script) {
					if (playgroundParticles.initialLocalVelocityMethod==MINMAXVECTOR3METHOD.Spherical)
						playgroundParticles.playgroundCache.initialLocalVelocity[p] = RandomRangeSpherical(random, playgroundParticles.initialLocalVelocityMin.x, playgroundParticles.initialLocalVelocityMax.x);
					else if (playgroundParticles.initialLocalVelocityMethod==MINMAXVECTOR3METHOD.SphericalLinear)
						playgroundParticles.playgroundCache.initialLocalVelocity[p] = RandomRangeSpherical(random, playgroundParticles.initialLocalVelocityMin.x, playgroundParticles.initialLocalVelocityMax.x, (p*1f)/(playgroundParticles.particleCount*1f));
					else if (playgroundParticles.initialLocalVelocityMethod==MINMAXVECTOR3METHOD.RectangularLinear)
						playgroundParticles.playgroundCache.initialLocalVelocity[p] = Vector3.Lerp (playgroundParticles.initialLocalVelocityMin, playgroundParticles.initialLocalVelocityMax, (p*1f)/(playgroundParticles.particleCount*1f));
					//else if (playgroundParticles.initialLocalVelocityMethod==MINMAXVECTOR3METHOD.SphericalSector)
					//	playgroundParticles.playgroundCache.initialLocalVelocity[p] = RandomRangeSpherical(random, playgroundParticles.initialLocalVelocityMin.x, playgroundParticles.initialLocalVelocityMax.x, playgroundParticles.initialLocalVelocityMin.y, playgroundParticles.initialLocalVelocityMax.y);
					//else if (playgroundParticles.initialLocalVelocityMethod==MINMAXVECTOR3METHOD.SphericalSectorLinear)
					//	playgroundParticles.playgroundCache.initialLocalVelocity[p] = RandomRangeSpherical(random, playgroundParticles.initialLocalVelocityMin.x, playgroundParticles.initialLocalVelocityMax.x, playgroundParticles.initialLocalVelocityMin.y, playgroundParticles.initialLocalVelocityMax.y, (p*1f)/(playgroundParticles.particleCount*1f));
					else playgroundParticles.playgroundCache.initialLocalVelocity[p] = RandomRange(random, playgroundParticles.initialLocalVelocityMin, playgroundParticles.initialLocalVelocityMax);

					playgroundParticles.playgroundCache.velocity[p] += playgroundParticles.playgroundCache.targetDirection[p];
					
					// Give this spawning particle its local velocity shape
					if (playgroundParticles.applyInitialVelocityShape)
						playgroundParticles.playgroundCache.velocity[p] = Vector3.Scale(playgroundParticles.playgroundCache.velocity[p], playgroundParticles.initialVelocityShape.Evaluate((p*1f)/(playgroundParticles.particleCount*1f), playgroundParticles.initialVelocityShapeScale));
				}
				
				// Initial stretch
				playgroundParticles.particleCache[p].velocity = playgroundParticles.renderModeStretch&&playgroundParticles.applyStretchStartDirection?playgroundParticles.stretchStartDirection:Vector3.zero;
			}
			if (playgroundParticles.source==SOURCEC.Script) {
				// Velocity for script mode
				if (!playgroundParticles.onlySourcePositioning && !playgroundParticles.onlyLifetimePositioning)
					playgroundParticles.playgroundCache.velocity[p] += playgroundParticles.scriptedEmissionVelocity;
				playgroundParticles.playgroundCache.targetPosition[p] = playgroundParticles.scriptedEmissionPosition;
				playgroundParticles.particleCache[p].velocity = playgroundParticles.renderModeStretch&&playgroundParticles.applyStretchStartDirection?playgroundParticles.stretchStartDirection:Vector3.zero;
			}
			
			// Set new random lifetime
			if (playgroundParticles.scriptedLifetime==0) {
				if (playgroundParticles.applyRandomLifetimeOnRebirth) {
					if (playgroundParticles.lifetimeValueMethod==VALUEMETHOD.Constant) {
						playgroundParticles.playgroundCache.lifetimeSubtraction[p] = 0;
					} else {
						playgroundParticles.playgroundCache.lifetimeSubtraction[p] = playgroundParticles.lifetime-RandomRange (random, playgroundParticles.lifetimeMin, playgroundParticles.lifetime);
					}
				}
				
				// Set shuriken particles lifetime
				if (!playgroundParticles.syncPositionsOnMainThread)
					playgroundParticles.particleCache[p].lifetime = playgroundParticles.lifetime;
				playgroundParticles.particleCache[p].startLifetime = playgroundParticles.lifetime-playgroundParticles.playgroundCache.lifetimeSubtraction[p];
			} else {
				
				playgroundParticles.playgroundCache.lifetimeSubtraction[p] = 0;
				if (!playgroundParticles.syncPositionsOnMainThread)
					playgroundParticles.particleCache[p].lifetime = playgroundParticles.scriptedLifetime;
				playgroundParticles.particleCache[p].startLifetime = playgroundParticles.scriptedLifetime;
			}
			
			if (playgroundParticles.playgroundCache.rebirth[p]) {
				
				playgroundParticles.SetParticleColorInternal(p, playgroundParticles.GetParticleColor(p, 0f, (p*1f)/(playgroundParticles.particleCount*1f)));
				
				// Source Scattering
				if (playgroundParticles.applySourceScatter && playgroundParticles.source!=SOURCEC.Script) {
					if (playgroundParticles.playgroundCache.scatterPosition[p]==Vector3.zero || playgroundParticles.applyRandomScatterOnRebirth) {
						if (playgroundParticles.sourceScatterMethod==MINMAXVECTOR3METHOD.Rectangular)
							playgroundParticles.playgroundCache.scatterPosition[p] = RandomRange(random, playgroundParticles.sourceScatterMin, playgroundParticles.sourceScatterMax);
						else if (playgroundParticles.sourceScatterMethod==MINMAXVECTOR3METHOD.RectangularLinear)
							playgroundParticles.playgroundCache.scatterPosition[p] = Vector3.Lerp (playgroundParticles.sourceScatterMin, playgroundParticles.sourceScatterMax, (p*1f)/(playgroundParticles.particleCount*1f));
						else if (playgroundParticles.sourceScatterMethod==MINMAXVECTOR3METHOD.SphericalLinear)
							playgroundParticles.playgroundCache.scatterPosition[p] = RandomRangeSpherical(random, playgroundParticles.sourceScatterMin.x, playgroundParticles.sourceScatterMax.x, (p*1f)/(playgroundParticles.particleCount*1f));
						//else if (playgroundParticles.sourceScatterMethod==MINMAXVECTOR3METHOD.SphericalSector)
						//	playgroundParticles.playgroundCache.scatterPosition[p] = RandomRangeSpherical(random, playgroundParticles.sourceScatterMin.x, playgroundParticles.sourceScatterMax.x, playgroundParticles.sourceScatterMin.y, playgroundParticles.sourceScatterMax.y);
						//else if (playgroundParticles.sourceScatterMethod==MINMAXVECTOR3METHOD.SphericalSectorLinear)
						//	playgroundParticles.playgroundCache.scatterPosition[p] = RandomRangeSpherical(random, playgroundParticles.sourceScatterMin.x, playgroundParticles.sourceScatterMax.x, playgroundParticles.sourceScatterMin.y, playgroundParticles.sourceScatterMax.y, (p*1f)/(playgroundParticles.particleCount*1f));
						else playgroundParticles.playgroundCache.scatterPosition[p] = RandomRangeSpherical(random, playgroundParticles.sourceScatterMin.x, playgroundParticles.sourceScatterMax.x);
					}
				} else playgroundParticles.playgroundCache.scatterPosition[p] = Vector3.zero;
				
				if (!playgroundParticles.onlyLifetimePositioning) {
					playgroundParticles.playgroundCache.position[p] = playgroundParticles.playgroundCache.targetPosition[p];
					if (!playgroundParticles.syncPositionsOnMainThread)
						playgroundParticles.particleCache[p].position = playgroundParticles.playgroundCache.targetPosition[p];
					playgroundParticles.playgroundCache.previousParticlePosition[p] = playgroundParticles.playgroundCache.targetPosition[p];
					playgroundParticles.playgroundCache.collisionParticlePosition[p] = playgroundParticles.playgroundCache.targetPosition[p];
				} else if (!playgroundParticles.onlySourcePositioning) {
					
					// Lifetime Positioning by Vector3 Animation Curve
					if (playgroundParticles.lifetimePositioningUsesSourceDirection && playgroundParticles.source!=SOURCEC.Script) {
						playgroundParticles.playgroundCache.position[p] = playgroundParticles.playgroundCache.targetPosition[p]+(playgroundParticles.playgroundCache.targetDirection[p]);
					} else {
						if (!playgroundParticles.applyLifetimePositioningPositionScale) {
							playgroundParticles.playgroundCache.position[p] = 
								playgroundParticles.playgroundCache.targetPosition[p]+
									playgroundParticles.lifetimePositioning.Evaluate(0, playgroundParticles.lifetimePositioningScale);
						} else {
							playgroundParticles.playgroundCache.position[p] = 
								playgroundParticles.playgroundCache.targetPosition[p]+
									playgroundParticles.lifetimePositioning.Evaluate(0, playgroundParticles.lifetimePositioningScale)*
									playgroundParticles.lifetimePositioningPositionScale.Evaluate(0);
						}
					}
					if (!playgroundParticles.syncPositionsOnMainThread)
						playgroundParticles.particleCache[p].position = playgroundParticles.playgroundCache.targetPosition[p];
					playgroundParticles.playgroundCache.previousParticlePosition[p] = playgroundParticles.playgroundCache.targetPosition[p];
					playgroundParticles.playgroundCache.collisionParticlePosition[p] = playgroundParticles.playgroundCache.targetPosition[p];
				}
				
				if (playgroundParticles.applyInitialColorOnRebirth) {
					playgroundParticles.SetParticleColorInternal(p, playgroundParticles.playgroundCache.initialColor[p]);
					playgroundParticles.playgroundCache.color[p] = playgroundParticles.playgroundCache.initialColor[p];
				}
			} else {
				playgroundParticles.particleCache[p].position = PlaygroundC.initialTargetPosition;
			}
			
			// Set new random rotation
			if (playgroundParticles.applyRandomRotationOnRebirth && !playgroundParticles.rotateTowardsDirection)
				playgroundParticles.playgroundCache.initialRotation[p] = RandomRange(random, playgroundParticles.initialRotationMin, playgroundParticles.initialRotationMax);
			
			if (!playgroundParticles.rotateTowardsDirection)
				playgroundParticles.playgroundCache.rotation[p] = playgroundParticles.playgroundCache.initialRotation[p];
			else {
				Vector3 particleDir;
				if (!playgroundParticles.onlySourcePositioning&&playgroundParticles.onlyLifetimePositioning)
					particleDir = (playgroundParticles.playgroundCache.position[p]+playgroundParticles.lifetimePositioning.Evaluate(.01f, playgroundParticles.lifetimePositioningScale))-playgroundParticles.playgroundCache.position[p];
				else
					particleDir = playgroundParticles.playgroundCache.velocity[p];
				playgroundParticles.playgroundCache.rotation[p] = playgroundParticles.playgroundCache.initialRotation[p]+SignedAngle(
					Vector3.up,
					particleDir,
					playgroundParticles.rotationNormal
					);
			}
			
			if (!playgroundParticles.syncPositionsOnMainThread)
				playgroundParticles.particleCache[p].rotation = playgroundParticles.playgroundCache.rotation[p];
			
			// Set size
			if (playgroundParticles.applyLifetimeSize && !playgroundParticles.applyParticleArraySize)
				playgroundParticles.playgroundCache.size[p] = playgroundParticles.playgroundCache.initialSize[p]*playgroundParticles.lifetimeSize.Evaluate(0)*playgroundParticles.scale;
			else if (playgroundParticles.applyLifetimeSize && playgroundParticles.applyParticleArraySize)
				playgroundParticles.playgroundCache.size[p] = playgroundParticles.playgroundCache.initialSize[p]*playgroundParticles.lifetimeSize.Evaluate(0)*playgroundParticles.particleArraySize.Evaluate((p*1f)/(playgroundParticles.particleCount*1f))*playgroundParticles.scale;
			else if (playgroundParticles.applyParticleArraySize)
				playgroundParticles.playgroundCache.size[p] = playgroundParticles.playgroundCache.initialSize[p]*playgroundParticles.particleArraySize.Evaluate((p*1f)/(playgroundParticles.particleCount*1f))*playgroundParticles.scale;
			else playgroundParticles.playgroundCache.size[p] = playgroundParticles.playgroundCache.initialSize[p]*playgroundParticles.scale;
			if (!playgroundParticles.syncPositionsOnMainThread)
			{
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
				playgroundParticles.particleCache[p].size = playgroundParticles.playgroundCache.maskAlpha[p]>0?playgroundParticles.playgroundCache.size[p]:0;
#else
				playgroundParticles.particleCache[p].startSize = playgroundParticles.playgroundCache.maskAlpha[p]>0?playgroundParticles.playgroundCache.size[p]:0;
#endif
			}
			
			// Set color gradient id
			if (playgroundParticles.colorSource==COLORSOURCEC.LifetimeColors && playgroundParticles.lifetimeColors.Count>0) {
				playgroundParticles.lifetimeColorId++;playgroundParticles.lifetimeColorId=playgroundParticles.lifetimeColorId%playgroundParticles.lifetimeColors.Count;
				playgroundParticles.playgroundCache.lifetimeColorId[p] = playgroundParticles.lifetimeColorId;
			}
			
			// Local Manipulators
			if (playgroundParticles.calculateManipulatorOnRebirth) {
				for (int m = 0; m<playgroundParticles.manipulators.Count; m++) {
					if (playgroundParticles.manipulators[m].transform!=null) {
						CalculateManipulator(playgroundParticles, playgroundParticles.manipulators[m], p, playgroundParticles.t, playgroundParticles.playgroundCache.life[p], playgroundParticles.playgroundCache.position[p], (playgroundParticles.localSpace?playgroundParticles.manipulators[m].transform.localPosition:playgroundParticles.manipulators[m].transform.position)+playgroundParticles.manipulatorFix, playgroundParticles.localSpace);
					}
				}
			}
			
			// Send birth event
			if (playgroundParticles.events.Count>0 && playgroundParticles.playgroundCache.rebirth[p])
				playgroundParticles.SendEvent(EVENTTYPEC.Birth, p);
			if (playgroundParticles.hasEventManipulatorLocal) {
				for (int i = 0; i<playgroundParticles.manipulators.Count; i++) {
					if (playgroundParticles.manipulators[i].trackParticles &&
					    playgroundParticles.manipulators[i].sendEventBirth &&
					    playgroundParticles.manipulators[i].Contains (playgroundParticles.playgroundCache.targetPosition[p], playgroundParticles.manipulators[i].transform.position)) {
						
						playgroundParticles.UpdateEventParticle(playgroundParticles.manipulators[i].manipulatorEventParticle, p);
						playgroundParticles.manipulators[i].SendParticleEventBirth();
					}
				}
			}
			if (playgroundParticles.hasEventManipulatorGlobal) {
				for (int i = 0; i<PlaygroundC.reference.manipulators.Count; i++) {
					if (PlaygroundC.reference.manipulators[i].trackParticles &&
					    PlaygroundC.reference.manipulators[i].sendEventBirth &&
					    PlaygroundC.reference.manipulators[i].Contains (playgroundParticles.playgroundCache.targetPosition[p], PlaygroundC.reference.manipulators[i].transform.position)) {
						
						playgroundParticles.UpdateEventParticle(PlaygroundC.reference.manipulators[i].manipulatorEventParticle, p);
						PlaygroundC.reference.manipulators[i].SendParticleEventBirth();
					}
				}
			}
		}
		/// <summary>
		/// Calculates the effect from Manipulator's properties.
		/// </summary>
		/// <param name="playgroundParticles">Playground particles.</param>
		/// <param name="thisManipulator">This manipulator.</param>
		/// <param name="thisManipulatorProperty">This manipulator property.</param>
		/// <param name="p">Particle index.</param>
		/// <param name="t">Delta time.</param>
		/// <param name="particlePosition">Particle position.</param>
		/// <param name="manipulatorPosition">Manipulator position.</param>
		/// <param name="localSpace">Is calculation in local space?</param>
		/// <param name="contains">Does the Manipulator contain the particle at index?</param>
		public static void PropertyManipulator (PlaygroundParticlesC playgroundParticles, ManipulatorObjectC thisManipulator, ManipulatorPropertyC thisManipulatorProperty, float manipulatorStrength, int p, float t, Vector3 particlePosition, Vector3 manipulatorPosition, float manipulatorDistance, bool localSpace, bool contains) {
			if (contains) {
				switch (thisManipulatorProperty.type) {
					
					// Math Property
				case MANIPULATORPROPERTYTYPEC.Math:
					if (thisManipulatorProperty.mathProperty.type == MATHMANIPULATORTYPE.Sin || thisManipulatorProperty.mathProperty.type == MATHMANIPULATORTYPE.Cos)
						t = playgroundParticles.localTime;
					switch (thisManipulatorProperty.mathProperty.property) {
					case MATHMANIPULATORPROPERTY.Position:
						playgroundParticles.playgroundCache.position[p] = thisManipulatorProperty.mathProperty.EvaluatePosition(playgroundParticles.playgroundCache.position[p], t);
						break;
					case MATHMANIPULATORPROPERTY.Velocity:
						playgroundParticles.playgroundCache.velocity[p] = thisManipulatorProperty.mathProperty.Evaluate(playgroundParticles.playgroundCache.velocity[p], t);
						break;
					case MATHMANIPULATORPROPERTY.Rotation:
						if (!playgroundParticles.rotateTowardsDirection)
							playgroundParticles.playgroundCache.rotation[p] = thisManipulatorProperty.mathProperty.Evaluate(playgroundParticles.playgroundCache.rotation[p], t)%360f;
						break;
					case MATHMANIPULATORPROPERTY.Size:
						playgroundParticles.playgroundCache.size[p] = thisManipulatorProperty.mathProperty.Evaluate(playgroundParticles.playgroundCache.size[p], t);
						playgroundParticles.playgroundCache.changedByPropertySize[p] = true;
						break;
					}
					break;
					
					// Velocity Property
				case MANIPULATORPROPERTYTYPEC.Velocity:
					if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None)
						playgroundParticles.playgroundCache.velocity[p] = thisManipulatorProperty.useLocalRotation?
							thisManipulatorProperty.localVelocity
							:
							thisManipulatorProperty.velocity;
					else {
						manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
						playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], thisManipulatorProperty.useLocalRotation?
						                                                               thisManipulatorProperty.localVelocity
						                                                               :
						                                                               thisManipulatorProperty.velocity, (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
					}
					break;
					
					// Additive Velocity Property
				case MANIPULATORPROPERTYTYPEC.AdditiveVelocity:
					manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
					playgroundParticles.playgroundCache.velocity[p] += thisManipulatorProperty.useLocalRotation?
						thisManipulatorProperty.localVelocity*((t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing)
							:
							thisManipulatorProperty.velocity*((t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
					break;
					
					// Color Property
				case MANIPULATORPROPERTYTYPEC.Color:
					Color staticColor;
					if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
						if (thisManipulatorProperty.keepColorAlphas) {
							staticColor = thisManipulatorProperty.color;
							staticColor.a = Mathf.Clamp(playgroundParticles.lifetimeColor.Evaluate(playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime).a, 0, staticColor.a);
							playgroundParticles.SetParticleColorInternal(p, staticColor);
						} else playgroundParticles.SetParticleColorInternal(p, thisManipulatorProperty.color);
					} else {
						if (thisManipulatorProperty.keepColorAlphas) {
							manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
							staticColor = thisManipulatorProperty.color;
							staticColor.a = Mathf.Clamp(playgroundParticles.lifetimeColor.Evaluate(playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime).a, 0, staticColor.a);
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
							playgroundParticles.SetParticleColorInternal(p, Color.Lerp(playgroundParticles.particleCache[p].color, staticColor, (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing));
#else
							playgroundParticles.SetParticleColorInternal(p, Color.Lerp(playgroundParticles.particleCache[p].startColor, staticColor, (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing));
#endif						
						}
						else 
						{
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
							playgroundParticles.SetParticleColorInternal(p, Color.Lerp(playgroundParticles.particleCache[p].color, thisManipulatorProperty.color, (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing));
#else
							playgroundParticles.SetParticleColorInternal(p, Color.Lerp(playgroundParticles.particleCache[p].startColor, thisManipulatorProperty.color, (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing));
#endif
						}
						playgroundParticles.playgroundCache.changedByPropertyColorLerp[p] = true;
					}
					
					// Only color in range of manipulator boundaries
					playgroundParticles.playgroundCache.changedByPropertyColor[p] = true;
					
					
					// Keep alpha of original color
					if (thisManipulatorProperty.keepColorAlphas)
						playgroundParticles.playgroundCache.changedByPropertyColorKeepAlpha[p] = true;
					
					// Set color pairing key
					if (playgroundParticles.playgroundCache.propertyColorId[p] != thisManipulator.manipulatorId) {
						playgroundParticles.playgroundCache.propertyColorId[p] = thisManipulator.manipulatorId;
					}
					break;
					
					// Lifetime Color Property
				case MANIPULATORPROPERTYTYPEC.LifetimeColor:
					if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
						playgroundParticles.SetParticleColorInternal(p, thisManipulatorProperty.lifetimeColor.Evaluate(playgroundParticles.lifetime>0?playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime:0));
					} else {
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
						playgroundParticles.SetParticleColorInternal(p, Color.Lerp(playgroundParticles.particleCache[p].color, thisManipulatorProperty.lifetimeColor.Evaluate(playgroundParticles.lifetime>0?playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime:0), (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing));
#else
						playgroundParticles.SetParticleColorInternal(p, Color.Lerp(playgroundParticles.particleCache[p].startColor, thisManipulatorProperty.lifetimeColor.Evaluate(playgroundParticles.lifetime>0?playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime:0), (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing));
#endif	
						playgroundParticles.playgroundCache.changedByPropertyColorLerp[p] = true;
					}
					
					// Only color in range of manipulator boundaries
					playgroundParticles.playgroundCache.changedByPropertyColor[p] = true;
					
					// Set color pairing key
					if (playgroundParticles.playgroundCache.propertyColorId[p] != thisManipulator.manipulatorId) {
						playgroundParticles.playgroundCache.propertyColorId[p] = thisManipulator.manipulatorId;
					}
					break;
					
					// Size Property
				case MANIPULATORPROPERTYTYPEC.Size:
					if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
						manipulatorDistance = thisManipulator.strengthDistanceEffect>0f?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:0;
						if (manipulatorDistance==0)
							playgroundParticles.playgroundCache.size[p] = thisManipulatorProperty.size;
						else
							playgroundParticles.playgroundCache.size[p] = thisManipulatorProperty.size+(thisManipulatorProperty.size/(1f+(manipulatorDistance/thisManipulator.strengthSmoothing))*(thisManipulator.strength*thisManipulatorProperty.strength));
					} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
						manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
						playgroundParticles.playgroundCache.size[p] = Mathf.Lerp(playgroundParticles.playgroundCache.size[p], thisManipulatorProperty.size, (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
					} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
						manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
						playgroundParticles.playgroundCache.size[p] = Mathf.MoveTowards(playgroundParticles.playgroundCache.size[p], thisManipulatorProperty.size, (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
					}
					
					playgroundParticles.playgroundCache.changedByPropertySize[p] = true;
					break;
					
					// Target Property
				case MANIPULATORPROPERTYTYPEC.Target:
					if (thisManipulatorProperty.targets.Count>0 && thisManipulatorProperty.targets[thisManipulatorProperty.targetPointer].available) {
						
						
						// Set target pointer
						if (playgroundParticles.playgroundCache.propertyId[p] != thisManipulator.manipulatorId) {
							
							playgroundParticles.playgroundCache.propertyTarget[p] = thisManipulatorProperty.targetPointer;
							thisManipulatorProperty.targetPointer++; thisManipulatorProperty.targetPointer=thisManipulatorProperty.targetPointer%thisManipulatorProperty.targets.Count;
							playgroundParticles.playgroundCache.propertyId[p] = thisManipulator.manipulatorId;
						}
						
						// Teleport or lerp to position based on transition type
						if (playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId && thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].available) {
							if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None)
								playgroundParticles.playgroundCache.position[p] = localSpace? 
									thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].localPosition
									: 
									thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].position;
							else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
								manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
								playgroundParticles.playgroundCache.position[p] = localSpace? 
									Vector3.Lerp(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].localPosition, (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing)
										:
										Vector3.Lerp(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].position, (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
								if (thisManipulatorProperty.zeroVelocityStrength>0)
									playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
							} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
								manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
								playgroundParticles.playgroundCache.position[p] = localSpace?
									Vector3.MoveTowards(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].localPosition, (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing)
										:
										Vector3.MoveTowards(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].position, (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
								if (thisManipulatorProperty.zeroVelocityStrength>0)
									playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
							}
							
							// This particle was changed by a target property
							playgroundParticles.playgroundCache.changedByPropertyTarget[p] = true;
						}
					}
					break;
					
					// Death Property
				case MANIPULATORPROPERTYTYPEC.Death:
					if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None)
						playgroundParticles.playgroundCache.life[p] = playgroundParticles.lifetime;
					else {
						manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
						playgroundParticles.playgroundCache.birth[p] -= (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing;
					}
					
					// This particle was changed by a death property
					playgroundParticles.playgroundCache.changedByPropertyDeath[p] = true;
					break;
					
					
					// Attractors
				case MANIPULATORPROPERTYTYPEC.Attractor:
					if (!playgroundParticles.onlySourcePositioning) {
						manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.Distance (manipulatorPosition, playgroundParticles.playgroundCache.position[p])/thisManipulator.strengthDistanceEffect:10f;
						playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], (manipulatorPosition-particlePosition)*((thisManipulatorProperty.strength*manipulatorStrength)/manipulatorDistance), t*((thisManipulatorProperty.strength*manipulatorStrength)/manipulatorDistance)/thisManipulator.strengthSmoothing);
					}
					break;
					
					// Attractors Gravitational
				case MANIPULATORPROPERTYTYPEC.Gravitational:
					if (!playgroundParticles.onlySourcePositioning) {
						manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.Distance (manipulatorPosition, playgroundParticles.playgroundCache.position[p])/thisManipulator.strengthDistanceEffect:10f;
						playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], (manipulatorPosition-particlePosition)*(thisManipulatorProperty.strength*manipulatorStrength)/manipulatorDistance, t/thisManipulator.strengthSmoothing);
					}
					break;
					
					// Repellents 
				case MANIPULATORPROPERTYTYPEC.Repellent:
					if (!playgroundParticles.onlySourcePositioning) {
						manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.Distance (manipulatorPosition, playgroundParticles.playgroundCache.position[p])/thisManipulator.strengthDistanceEffect:10f;
						playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], (particlePosition-manipulatorPosition)*((thisManipulatorProperty.strength*manipulatorStrength)/manipulatorDistance), t*((thisManipulatorProperty.strength*manipulatorStrength)/manipulatorDistance)/thisManipulator.strengthSmoothing);
					}
					break;
					
					// Vortex
				case MANIPULATORPROPERTYTYPEC.Vortex:
					if (!playgroundParticles.onlySourcePositioning) {
						manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.Distance (manipulatorPosition, playgroundParticles.playgroundCache.position[p])/thisManipulator.strengthDistanceEffect:10f;
						playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], ((manipulatorPosition-particlePosition)*(manipulatorStrength*thisManipulatorProperty.strength)/manipulatorDistance)-Vector3.Cross(thisManipulator.transform.up, (manipulatorPosition-particlePosition))*(manipulatorStrength*thisManipulatorProperty.strength)/manipulatorDistance, (t*(manipulatorStrength*thisManipulatorProperty.strength)/manipulatorDistance)/thisManipulator.strengthSmoothing);
					}
					break;
					
					// Turbulence
				case MANIPULATORPROPERTYTYPEC.Turbulence:
					if (!playgroundParticles.onlySourcePositioning && thisManipulatorProperty.turbulenceType!=TURBULENCETYPE.None) {
						manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.Distance (manipulatorPosition, particlePosition)/thisManipulator.strengthDistanceEffect:10f;
						Turbulence (
							playgroundParticles,
							thisManipulatorProperty.turbulenceSimplex,
							p,
							t/thisManipulator.strengthSmoothing, 
							thisManipulatorProperty.turbulenceType, 
							thisManipulatorProperty.turbulenceTimeScale, 
							thisManipulatorProperty.turbulenceScale,
							((thisManipulatorProperty.strength*manipulatorStrength)/manipulatorDistance),
							thisManipulatorProperty.turbulenceApplyLifetimeStrength,
							thisManipulatorProperty.turbulenceLifetimeStrength
							);
					}
					break;
					
					// Mesh Target
				case MANIPULATORPROPERTYTYPEC.MeshTarget:
					if (!playgroundParticles.onlySourcePositioning && thisManipulatorProperty.meshTarget.initialized) {
						
						// Set target pointer
						if (playgroundParticles.playgroundCache.propertyId[p] != thisManipulator.manipulatorId) {
							playgroundParticles.playgroundCache.propertyTarget[p] = thisManipulatorProperty.targetSortingList[thisManipulatorProperty.targetPointer];
							thisManipulatorProperty.targetPointer++; thisManipulatorProperty.targetPointer=thisManipulatorProperty.targetPointer%thisManipulatorProperty.meshTarget.vertexPositions.Length;
							playgroundParticles.playgroundCache.propertyId[p] = thisManipulator.manipulatorId;
						}
						
						// Teleport or lerp to position based on transition type
						if (playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId) {
							if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
								playgroundParticles.playgroundCache.position[p] = thisManipulatorProperty.meshTargetMatrix.MultiplyPoint3x4(thisManipulatorProperty.meshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.meshTarget.vertexPositions.Length]);
								playgroundParticles.playgroundCache.velocity[p] = Vector3.zero;
							} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
								playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(particlePosition, thisManipulatorProperty.meshTargetMatrix.MultiplyPoint3x4(thisManipulatorProperty.meshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.meshTarget.vertexPositions.Length]), (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
								if (thisManipulatorProperty.zeroVelocityStrength>0)
									playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
							} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
								playgroundParticles.playgroundCache.position[p] = Vector3.MoveTowards(particlePosition, thisManipulatorProperty.meshTargetMatrix.MultiplyPoint3x4(thisManipulatorProperty.meshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.meshTarget.vertexPositions.Length]), (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
								if (thisManipulatorProperty.zeroVelocityStrength>0)
									playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
							}
							
							// This particle was changed by a target property
							playgroundParticles.playgroundCache.changedByPropertyTarget[p] = true;
						}
						
					}
					break;
					
					// Skinned Mesh Target
				case MANIPULATORPROPERTYTYPEC.SkinnedMeshTarget:
					if (!playgroundParticles.onlySourcePositioning && thisManipulatorProperty.skinnedMeshTarget.initialized) {
						
						// Set target pointer
						if (playgroundParticles.playgroundCache.propertyId[p] != thisManipulator.manipulatorId) {
							playgroundParticles.playgroundCache.propertyTarget[p] = thisManipulatorProperty.targetSortingList[thisManipulatorProperty.targetPointer];
							thisManipulatorProperty.targetPointer++; thisManipulatorProperty.targetPointer=thisManipulatorProperty.targetPointer%thisManipulatorProperty.skinnedMeshTarget.vertexPositions.Length;
							playgroundParticles.playgroundCache.propertyId[p] = thisManipulator.manipulatorId;
						}
						
						// Teleport or lerp to position based on transition type
						if (playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId) {
							if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
								playgroundParticles.playgroundCache.position[p] = thisManipulatorProperty.skinnedMeshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.skinnedMeshTarget.vertexPositions.Length];
								playgroundParticles.playgroundCache.velocity[p] = Vector3.zero;
							} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
								manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
								playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(particlePosition, thisManipulatorProperty.skinnedMeshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.skinnedMeshTarget.vertexPositions.Length], t*(thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
								if (thisManipulatorProperty.zeroVelocityStrength>0)
									playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
							} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
								manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
								playgroundParticles.playgroundCache.position[p] = Vector3.MoveTowards(particlePosition, thisManipulatorProperty.skinnedMeshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.skinnedMeshTarget.vertexPositions.Length], t*(thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
								if (thisManipulatorProperty.zeroVelocityStrength>0)
									playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
							}
							
							// This particle was changed by a target property
							playgroundParticles.playgroundCache.changedByPropertyTarget[p] = true;
						}
					}
					break;
					
					// State Target
				case MANIPULATORPROPERTYTYPEC.StateTarget:
					if (!playgroundParticles.onlySourcePositioning && thisManipulatorProperty.stateTarget.initialized && !thisManipulatorProperty.stateTarget.IsInitializing()) {
						
						// Set target pointer
						if (playgroundParticles.playgroundCache.propertyId[p] != thisManipulator.manipulatorId) {
							playgroundParticles.playgroundCache.propertyTarget[p] = thisManipulatorProperty.targetSortingList[thisManipulatorProperty.targetPointer%thisManipulatorProperty.targetSortingList.Length];
							thisManipulatorProperty.targetPointer++; thisManipulatorProperty.targetPointer=thisManipulatorProperty.targetPointer%thisManipulatorProperty.stateTarget.positionLength;
							playgroundParticles.playgroundCache.propertyId[p] = thisManipulator.manipulatorId;
						}
						
						// Teleport or lerp to position based on transition type
						if (playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId) {
							Vector3 newPos = thisManipulatorProperty.stateTarget.stateTransformMx.MultiplyPoint3x4(thisManipulatorProperty.stateTarget.GetPosition(playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.stateTarget.positionLength));
							if (!thisManipulatorProperty.onlyPositionInRange || thisManipulator.shape == MANIPULATORSHAPEC.Infinite || thisManipulatorProperty.onlyPositionInRange && thisManipulator.Contains (newPos, manipulatorPosition)) {
								if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
									playgroundParticles.playgroundCache.position[p] = newPos;
									playgroundParticles.playgroundCache.velocity[p] = Vector3.zero;
								} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
									manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
									playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(particlePosition, newPos, t*(thisManipulatorProperty.strength*thisManipulator.strength/manipulatorDistance)/thisManipulator.strengthSmoothing);
									if (thisManipulatorProperty.zeroVelocityStrength>0)
										playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
								} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
									manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
									playgroundParticles.playgroundCache.position[p] = Vector3.MoveTowards(particlePosition, newPos, t*(thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
									if (thisManipulatorProperty.zeroVelocityStrength>0)
										playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
								}
								
								// This particle was changed by a target property
								playgroundParticles.playgroundCache.changedByPropertyTarget[p] = true;
							}
							
							
						}
						
					}
					break;
					
					// Spline Target
				case MANIPULATORPROPERTYTYPEC.SplineTarget:
					if (!playgroundParticles.onlySourcePositioning && thisManipulatorProperty.SplineTargetIsReady()) {
						
						// Set target pointer
						if (playgroundParticles.playgroundCache.propertyId[p] != thisManipulator.manipulatorId) {
							playgroundParticles.playgroundCache.propertyId[p] = thisManipulator.manipulatorId;
						}
						
						// Teleport or lerp to position based on transition type
						if (playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId) {
							float timePos;
							if (thisManipulatorProperty.splineTargetMethod==SPLINETARGETMETHOD.SplineTime)
								timePos = ((p*1f)/(playgroundParticles.particleCount*1f))+thisManipulatorProperty.splineTimeOffset;
							else
								timePos = Mathf.Clamp01((playgroundParticles.playgroundCache.life[p] / ((playgroundParticles.playgroundCache.death[p]-playgroundParticles.playgroundCache.birth[p])-playgroundParticles.playgroundCache.lifetimeSubtraction[p]))+thisManipulatorProperty.splineTimeOffset);

							if (Mathf.Approximately(thisManipulatorProperty.splineTimeOffset, 0) && Mathf.Approximately(timePos, 1f))
								timePos = .9999f;
							Vector3 newPos = thisManipulatorProperty.splineTarget.GetPoint(timePos);
							if (!thisManipulatorProperty.onlyPositionInRange || thisManipulator.shape == MANIPULATORSHAPEC.Infinite || thisManipulatorProperty.onlyPositionInRange && thisManipulator.Contains (newPos, manipulatorPosition)) {
								if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
									playgroundParticles.playgroundCache.position[p] = newPos;
									playgroundParticles.playgroundCache.velocity[p] = Vector3.zero;
								} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
									manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
									playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(particlePosition, newPos, t*(thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
									if (thisManipulatorProperty.zeroVelocityStrength>0)
										playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
								} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
									manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
									playgroundParticles.playgroundCache.position[p] = Vector3.MoveTowards(particlePosition, newPos, t*(thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
									if (thisManipulatorProperty.zeroVelocityStrength>0)
										playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
								}
								
								// This particle was changed by a target property
								playgroundParticles.playgroundCache.changedByPropertyTarget[p] = true;
							}
							
							
						}
						
					}
					break;
				}
				
				playgroundParticles.playgroundCache.changedByProperty[p] = true;
				
			} else {
				
				// Handle size outside
				if (thisManipulatorProperty.onlySizeInRange)
					playgroundParticles.playgroundCache.changedByPropertySize[p] = false;
				
				// Handle colors outside of property manipulator range
				if (playgroundParticles.playgroundCache.propertyColorId[p] == thisManipulator.manipulatorId && (thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.Color || thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.LifetimeColor)) {
					
					// Lerp back color with previous set key
					if (playgroundParticles.playgroundCache.changedByPropertyColorLerp[p] && thisManipulatorProperty.transition != MANIPULATORPROPERTYTRANSITIONC.None && thisManipulatorProperty.onlyColorInRange) {
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
						playgroundParticles.SetParticleColorInternal(p, Color.Lerp(playgroundParticles.particleCache[p].color, playgroundParticles.lifetimeColor.Evaluate(playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime), t*thisManipulatorProperty.strength*manipulatorStrength));
#else
						playgroundParticles.SetParticleColorInternal(p, Color.Lerp(playgroundParticles.particleCache[p].startColor, playgroundParticles.lifetimeColor.Evaluate(playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime), t*thisManipulatorProperty.strength*manipulatorStrength));
#endif					
					} 
					
					if (thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.LifetimeColor && !thisManipulatorProperty.onlyColorInRange) {
						if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.None) {
							playgroundParticles.SetParticleColorInternal(p, thisManipulatorProperty.lifetimeColor.Evaluate(playgroundParticles.lifetime>0?playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime:0));
						} else {
							manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
							playgroundParticles.SetParticleColorInternal(p, Color.Lerp(playgroundParticles.particleCache[p].color, thisManipulatorProperty.lifetimeColor.Evaluate(playgroundParticles.lifetime>0?playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime:0), (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing));
#else
							playgroundParticles.SetParticleColorInternal(p, Color.Lerp(playgroundParticles.particleCache[p].startColor, thisManipulatorProperty.lifetimeColor.Evaluate(playgroundParticles.lifetime>0?playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime:0), (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing));
#endif
						}
					}
					
					if (thisManipulatorProperty.onlyColorInRange)
						playgroundParticles.playgroundCache.changedByPropertyColor[p] = false;
				}
				
				// Position onto targets when outside of range
				if (!playgroundParticles.onlySourcePositioning && !(thisManipulatorProperty.onlyPositionInRange || thisManipulator.shape == MANIPULATORSHAPEC.Infinite) && thisManipulatorProperty.transition != MANIPULATORPROPERTYTRANSITIONC.None) {
					
					// Target (Transform) positioning outside of range
					if (thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.Target) {
						if (thisManipulatorProperty.targets.Count>0 && thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count]!=null) {
							if (playgroundParticles.playgroundCache.changedByPropertyTarget[p] && thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].available && playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.transform.GetInstanceID()) {
								if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp)
									playgroundParticles.playgroundCache.position[p] = localSpace?
										Vector3.Lerp(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].localPosition, t*(thisManipulatorProperty.strength*manipulatorStrength)/thisManipulator.strengthSmoothing)
										:	
										Vector3.Lerp(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].position, t*(thisManipulatorProperty.strength*manipulatorStrength)/thisManipulator.strengthSmoothing);
								else
									playgroundParticles.playgroundCache.position[p] = localSpace?
										Vector3.MoveTowards(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].localPosition, t*(thisManipulatorProperty.strength*manipulatorStrength)/thisManipulator.strengthSmoothing)
										:
										Vector3.MoveTowards(particlePosition, thisManipulatorProperty.targets[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.targets.Count].position, t*(thisManipulatorProperty.strength*manipulatorStrength)/thisManipulator.strengthSmoothing);
								
								if (thisManipulatorProperty.zeroVelocityStrength>0)
									playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
							}
						}
					}
					
					// Mesh Target positioning outside of range
					if (thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.MeshTarget && thisManipulatorProperty.meshTarget.initialized && playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId) {
						if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
							manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
							playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(particlePosition, thisManipulatorProperty.meshTargetMatrix.MultiplyPoint3x4(thisManipulatorProperty.meshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.meshTarget.vertexPositions.Length]), (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
							if (thisManipulatorProperty.zeroVelocityStrength>0)
								playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
						} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
							manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
							playgroundParticles.playgroundCache.position[p] = Vector3.MoveTowards(particlePosition, thisManipulatorProperty.meshTargetMatrix.MultiplyPoint3x4(thisManipulatorProperty.meshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.meshTarget.vertexPositions.Length]), (t*thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
							if (thisManipulatorProperty.zeroVelocityStrength>0)
								playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
						}
					}
					
					// Skinned Mesh Target positioning outside of range
					if (thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.SkinnedMeshTarget && thisManipulatorProperty.skinnedMeshTarget.initialized && playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId) {
						if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
							manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
							playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(particlePosition, thisManipulatorProperty.skinnedMeshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.skinnedMeshTarget.vertexPositions.Length], t*(thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
							if (thisManipulatorProperty.zeroVelocityStrength>0)
								playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
						} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
							manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
							playgroundParticles.playgroundCache.position[p] = Vector3.MoveTowards(particlePosition, thisManipulatorProperty.skinnedMeshTarget.vertexPositions[playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.skinnedMeshTarget.vertexPositions.Length], t*(thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
							if (thisManipulatorProperty.zeroVelocityStrength>0)
								playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
						}
					}
					
					// State Target positioning outside of range
					if (thisManipulatorProperty.type == MANIPULATORPROPERTYTYPEC.StateTarget && thisManipulatorProperty.stateTarget.initialized && !thisManipulatorProperty.stateTarget.IsInitializing() && playgroundParticles.playgroundCache.propertyId[p] == thisManipulator.manipulatorId) {
						if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Lerp) {
							manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
							playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(particlePosition, thisManipulatorProperty.stateTarget.stateTransformMx.MultiplyPoint3x4(thisManipulatorProperty.stateTarget.GetPosition(playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.stateTarget.positionLength)), t*(thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
							if (thisManipulatorProperty.zeroVelocityStrength>0)
								playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
						} else if (thisManipulatorProperty.transition == MANIPULATORPROPERTYTRANSITIONC.Linear) {
							manipulatorDistance = thisManipulator.strengthDistanceEffect>0?Vector3.SqrMagnitude (manipulatorPosition - particlePosition)/thisManipulator.strengthDistanceEffect:10f;
							playgroundParticles.playgroundCache.position[p] = Vector3.MoveTowards(particlePosition, thisManipulatorProperty.stateTarget.stateTransformMx.MultiplyPoint3x4(thisManipulatorProperty.stateTarget.GetPosition(playgroundParticles.playgroundCache.propertyTarget[p]%thisManipulatorProperty.stateTarget.positionLength)), t*(thisManipulatorProperty.strength*manipulatorStrength/manipulatorDistance)/thisManipulator.strengthSmoothing);
							if (thisManipulatorProperty.zeroVelocityStrength>0)
								playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], Vector3.zero, t*thisManipulatorProperty.zeroVelocityStrength);
						}
					}
				}
			}
		}
		/// <summary>
		/// Asynchronous-friendly particle calculation routine.
		/// </summary>
		public static void ThreadedCalculations (PlaygroundParticlesC playgroundParticles) {

			if (playgroundParticles.inPlayback)
			{
				playgroundParticles.isDoneThread = true;
				playgroundParticles.threadHadNoActiveParticles = false;
				return;
			}

			// Refresh delta time
			if (!playgroundParticles.isPrewarming) {
				playgroundParticles.localDeltaTime = (PlaygroundC.globalTime-playgroundParticles.lastTimeUpdated)*playgroundParticles.particleTimescale;
				playgroundParticles.localTime += playgroundParticles.localDeltaTime;
				playgroundParticles.lastTimeUpdated = PlaygroundC.globalTime;
			}
			
			// Set delta time
			playgroundParticles.t = playgroundParticles.localDeltaTime;
			
			if (playgroundParticles.particleCount<=0 || 
			    playgroundParticles.playgroundCache.color.Length!=playgroundParticles.particleCount || 
			    playgroundParticles.playgroundCache.targetPosition.Length!=playgroundParticles.particleCount ||
			    playgroundParticles.playgroundCache.targetDirection.Length!=playgroundParticles.particleCount ||
			    playgroundParticles.source==SOURCEC.State && playgroundParticles.states[playgroundParticles.activeState].IsInitializing() ||
			    playgroundParticles.isYieldRefreshing || !PlaygroundC.IsReady() || playgroundParticles.isSettingParticleTime) {
				playgroundParticles.isDoneThread = true;
				playgroundParticles.threadHadNoActiveParticles = false;
				return;
			}
			if (PlaygroundC.reference.calculate && playgroundParticles.calculate && !playgroundParticles.inTransition && playgroundParticles.hasActiveParticles) {}
			else if (playgroundParticles.source!=SOURCEC.Script) {
				playgroundParticles.isDoneThread = true;
				playgroundParticles.cameFromNonCalculatedFrame = true;
				return;
			} else {
				playgroundParticles.isDoneThread = true;
				return;
			}
			
			// Check that simplex turbulence is available (will be next frame in case not)
			if (!playgroundParticles.onlySourcePositioning && !playgroundParticles.onlyLifetimePositioning && playgroundParticles.turbulenceStrength>0 && playgroundParticles.turbulenceType!=TURBULENCETYPE.None) {
				if (playgroundParticles.turbulenceType==TURBULENCETYPE.Simplex && playgroundParticles.turbulenceSimplex==null) {
					playgroundParticles.isDoneThread = true;
					playgroundParticles.threadHadNoActiveParticles = false;
					return;
				}
			}
			
			float t = playgroundParticles.t;
			
			// Prepare variables for particle source positions
			Matrix4x4 fMx = new Matrix4x4();
			if (playgroundParticles.source==SOURCEC.State || playgroundParticles.source==SOURCEC.WorldObject || playgroundParticles.source==SOURCEC.SkinnedWorldObject) {
				fMx.SetTRS(Vector3.zero, playgroundParticles.stRot, new Vector3(1f,1f,1f));
			}
			
			bool noActiveParticles = true;
			if (playgroundParticles.source==SOURCEC.Transform)
				for (int i = 0; i<playgroundParticles.sourceTransforms.Count; i++)
					playgroundParticles.sourceTransforms[i].UpdateMatrix();
			
			// Update skinned mesh vertices
			if (playgroundParticles.source==SOURCEC.SkinnedWorldObject && playgroundParticles.skinnedWorldObjectReady && !playgroundParticles.forceSkinnedMeshUpdateOnMainThread && PlaygroundC.reference.skinnedMeshThreadMethod==ThreadMethodComponent.InsideParticleCalculation) {
				playgroundParticles.skinnedWorldObject.Update();
			}
			
			// Misc
			int pCount = playgroundParticles.particleCache.Length;
			
			// Check that cache is correct
			if (playgroundParticles.playgroundCache.lifetimeSubtraction.Length!=pCount)
				SetLifetimeSubtraction(playgroundParticles);
			if (playgroundParticles.playgroundCache.maskAlpha.Length!=pCount) {
				playgroundParticles.playgroundCache.maskAlpha = new float[pCount];
				playgroundParticles.playgroundCache.isMasked = new bool[pCount];
			}
			if (playgroundParticles.playgroundCache.manipulatorId.Length!=pCount)
				playgroundParticles.playgroundCache.manipulatorId = new int[pCount];
			if (playgroundParticles.playgroundCache.excludeFromManipulatorId.Length!=pCount)
				playgroundParticles.playgroundCache.excludeFromManipulatorId = new int[pCount];
			if (playgroundParticles.playgroundCache.noForce.Length!=pCount)
				playgroundParticles.playgroundCache.noForce = new bool[pCount];
			if (playgroundParticles.playgroundCache.isNonBirthed.Length!=pCount)
				playgroundParticles.playgroundCache.isNonBirthed = new bool[pCount];
			if (playgroundParticles.playgroundCache.isFirstLoop.Length!=pCount)
				playgroundParticles.playgroundCache.isFirstLoop = new bool[pCount];
			if (playgroundParticles.playgroundCache.isCalculatedThisFrame.Length!=pCount)
				playgroundParticles.playgroundCache.isCalculatedThisFrame = new bool[pCount];
			if (playgroundParticles.playgroundCache.simulate.Length!=pCount) {
				playgroundParticles.playgroundCache.simulate = new bool[pCount];
				for (int p = 0; p<pCount; p++)
					playgroundParticles.playgroundCache.simulate[p] = true;
			}

			bool hasLifetimeLoss = playgroundParticles.collision && playgroundParticles.lifetimeLoss > 0;
			if (hasLifetimeLoss && (playgroundParticles.playgroundCache.lifetimeLoss==null || playgroundParticles.playgroundCache.lifetimeLoss.Length!=pCount))
				playgroundParticles.playgroundCache.lifetimeLoss = new float[pCount];

			if (playgroundParticles.applyParticleMask && (playgroundParticles.playgroundCache.maskSorting==null || playgroundParticles.playgroundCache.maskSorting.Length!=pCount || playgroundParticles.particleMaskSorting!=playgroundParticles.previousMaskSorting))
				playgroundParticles.RefreshMaskSorting();
			
			Vector3 zero = Vector3.zero;
			Vector3 up = Vector3.up;
			float initYpos = PlaygroundC.initialTargetPosition.y;

			
			// Calculation loop
			for (int p = 0; p<playgroundParticles.particleCount; p++) {
				
				// Check that particle count is correct
				if (pCount != playgroundParticles.particleCache.Length || playgroundParticles.isYieldRefreshing || playgroundParticles.isSettingParticleTime || playgroundParticles.isSettingParticleCount) {
					playgroundParticles.cameFromNonEmissionFrame = false;
					playgroundParticles.isDoneThread = true;
					playgroundParticles.threadHadNoActiveParticles = false;
					return;
				}
				
				// Check simulation
				if (!playgroundParticles.playgroundCache.simulate[p]) {
					if (playgroundParticles.playgroundCache.rebirth[p] && playgroundParticles.loop) {
						playgroundParticles.InactivateParticle(p);
					}
					continue;
				} else {
					noActiveParticles = false;
				}
				
				// This particle is about to be calculated
				playgroundParticles.playgroundCache.isCalculatedThisFrame[p] = false;
				
				// Prepare variables inside scope
				float lifeInSeconds = (playgroundParticles.playgroundCache.death[p]-playgroundParticles.playgroundCache.birth[p])-playgroundParticles.playgroundCache.lifetimeSubtraction[p];
				float normalizedLife = Mathf.Clamp01(playgroundParticles.playgroundCache.life[p]/lifeInSeconds);
				float normalizedP = (p*1f)/(playgroundParticles.particleCount*1f);
				float lifetimePositioningTimeScale = 1f;
				if (playgroundParticles.applyLifetimePositioningTimeScale)
					lifetimePositioningTimeScale = playgroundParticles.lifetimePositioningTimeScale.Evaluate(normalizedLife);
				
				// Apply particle mask
				if (playgroundParticles.applyParticleMask) {
					int maskedP = playgroundParticles.playgroundCache.maskSorting[p];
					if (maskedP>=0 && maskedP<playgroundParticles.particleCount) {
						if (p<playgroundParticles.particleMask) {
							if (playgroundParticles.playgroundCache.maskAlpha[maskedP]<=0 || playgroundParticles.particleMaskTime<=0) {
								playgroundParticles.playgroundCache.isMasked[maskedP] = true;
								playgroundParticles.playgroundCache.maskAlpha[maskedP] = 0;
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
								playgroundParticles.particleCache[maskedP].size = 0;
#else
								playgroundParticles.particleCache[maskedP].startSize = 0;
#endif
							} else {
								playgroundParticles.playgroundCache.maskAlpha[maskedP] -= (1f/playgroundParticles.particleMaskTime)*playgroundParticles.localDeltaTime;
							}
						} else {
							if (playgroundParticles.playgroundCache.maskAlpha[maskedP]>=1f || playgroundParticles.particleMaskTime<=0) {
								playgroundParticles.playgroundCache.isMasked[maskedP] = false;
								playgroundParticles.playgroundCache.maskAlpha[maskedP] = 1f;
							} else {
								playgroundParticles.playgroundCache.maskAlpha[maskedP] += (1f/playgroundParticles.particleMaskTime)*playgroundParticles.localDeltaTime;
							}
						}
					}
				} else {
					playgroundParticles.playgroundCache.isMasked[p] = false;
					playgroundParticles.playgroundCache.maskAlpha[p] = 1f;
				}
				
				Color32 lifetimeColor = playgroundParticles.GetParticleColor(p, normalizedLife, normalizedP);
				
				// Assign color to particle
				playgroundParticles.SetParticleColorInternal(p, lifetimeColor);
				
				// Give Playground Cache its color value
				playgroundParticles.playgroundCache.color[p] = lifetimeColor;
				
				// Source positions
				if (playgroundParticles.emit) {
					if (!playgroundParticles.syncPositionsOnMainThread)
						playgroundParticles.playgroundCache.previousTargetPosition[p] = playgroundParticles.playgroundCache.targetPosition[p];
					switch (playgroundParticles.source) {
					case SOURCEC.State:
						if (playgroundParticles.playgroundCache.rebirth[p] || playgroundParticles.onlySourcePositioning || playgroundParticles.onlyLifetimePositioning) {
							
							if (playgroundParticles.applyInitialLocalVelocity && !playgroundParticles.onlyLifetimePositioning)
								playgroundParticles.playgroundCache.targetDirection[p] = fMx.MultiplyPoint3x4(Vector3Scale(playgroundParticles.playgroundCache.initialLocalVelocity[p], playgroundParticles.states[playgroundParticles.activeState].GetNormal(p)));
							if (playgroundParticles.onlyLifetimePositioning) {
								playgroundParticles.playgroundCache.targetDirection[p] = fMx.MultiplyPoint3x4(Vector3Scale(playgroundParticles.lifetimePositioning.Evaluate(normalizedLife*lifetimePositioningTimeScale, playgroundParticles.lifetimePositioningScale), playgroundParticles.states[playgroundParticles.activeState].GetNormal(p)));
								if (playgroundParticles.applyLifetimePositioningPositionScale)
									playgroundParticles.playgroundCache.targetDirection[p] *= playgroundParticles.lifetimePositioningPositionScale.Evaluate(normalizedLife);
							}
							
							playgroundParticles.SetSourcePosition(p);
							
							// Local space compensation calculation
							if (playgroundParticles.localSpace && playgroundParticles.applyLocalSpaceMovementCompensation)
								playgroundParticles.playgroundCache.localSpaceMovementCompensation[p] = playgroundParticles.playgroundCache.targetPosition[p]-playgroundParticles.playgroundCache.previousTargetPosition[p];
						}
						break;
					case SOURCEC.Transform:
						if (playgroundParticles.playgroundCache.rebirth[p] || playgroundParticles.onlySourcePositioning || playgroundParticles.onlyLifetimePositioning) {

							if (playgroundParticles.applyInitialLocalVelocity && !playgroundParticles.onlyLifetimePositioning)
								if (playgroundParticles.localSpace && playgroundParticles.transformIndex!=playgroundParticles.psTransformNum)
									playgroundParticles.playgroundCache.targetDirection[p] = playgroundParticles.particleSystemInverseRotation*playgroundParticles.sourceTransforms[playgroundParticles.transformIndex].rotation*playgroundParticles.playgroundCache.initialLocalVelocity[p];
							else
								playgroundParticles.playgroundCache.targetDirection[p] = playgroundParticles.sourceTransforms[playgroundParticles.transformIndex].rotation*playgroundParticles.playgroundCache.initialLocalVelocity[p];
							if (playgroundParticles.onlyLifetimePositioning) {
								playgroundParticles.playgroundCache.targetDirection[p] = playgroundParticles.sourceTransforms[playgroundParticles.transformIndex].rotation*playgroundParticles.lifetimePositioning.Evaluate(normalizedLife*lifetimePositioningTimeScale, playgroundParticles.lifetimePositioningScale);
								if (playgroundParticles.applyLifetimePositioningPositionScale)
									playgroundParticles.playgroundCache.targetDirection[p] *= playgroundParticles.lifetimePositioningPositionScale.Evaluate(normalizedLife*lifetimePositioningTimeScale);
							}
							
							playgroundParticles.SetSourcePosition(p);
							
							// Local space compensation calculation
							if (playgroundParticles.localSpace && playgroundParticles.applyLocalSpaceMovementCompensation)
								playgroundParticles.playgroundCache.localSpaceMovementCompensation[p] = playgroundParticles.playgroundCache.targetPosition[p]-playgroundParticles.playgroundCache.previousTargetPosition[p];
						}
						break;
					case SOURCEC.WorldObject:
						if (playgroundParticles.playgroundCache.rebirth[p] || playgroundParticles.onlySourcePositioning || playgroundParticles.onlyLifetimePositioning) {
							if (playgroundParticles.applyInitialLocalVelocity && !playgroundParticles.onlyLifetimePositioning)
								playgroundParticles.playgroundCache.targetDirection[p] = fMx.MultiplyPoint3x4(Vector3Scale(playgroundParticles.playgroundCache.initialLocalVelocity[p], playgroundParticles.worldObject.normals[p%playgroundParticles.worldObject.normals.Length]));
							if (playgroundParticles.onlyLifetimePositioning) {
								playgroundParticles.playgroundCache.targetDirection[p] = fMx.MultiplyPoint3x4(Vector3Scale(playgroundParticles.lifetimePositioning.Evaluate(normalizedLife*lifetimePositioningTimeScale, playgroundParticles.lifetimePositioningScale), playgroundParticles.worldObject.normals[p%playgroundParticles.worldObject.normals.Length]));
								if (playgroundParticles.applyLifetimePositioningPositionScale)
									playgroundParticles.playgroundCache.targetDirection[p] *= playgroundParticles.lifetimePositioningPositionScale.Evaluate(normalizedLife);
							}
							playgroundParticles.SetSourcePosition(p);
							
							// Local space compensation calculation
							if (playgroundParticles.localSpace && playgroundParticles.applyLocalSpaceMovementCompensation)
								playgroundParticles.playgroundCache.localSpaceMovementCompensation[p] = (playgroundParticles.playgroundCache.targetPosition[p]-playgroundParticles.playgroundCache.previousTargetPosition[p]);
						}
						break;
					case SOURCEC.SkinnedWorldObject:
						if (playgroundParticles.skinnedWorldObjectReady) {
							if (playgroundParticles.playgroundCache.rebirth[p] || playgroundParticles.onlySourcePositioning || playgroundParticles.onlyLifetimePositioning) {
								if (playgroundParticles.applyInitialLocalVelocity && !playgroundParticles.onlyLifetimePositioning)
									playgroundParticles.playgroundCache.targetDirection[p] = fMx.MultiplyPoint3x4(Vector3Scale(playgroundParticles.playgroundCache.initialLocalVelocity[p], playgroundParticles.skinnedWorldObject.normals[p%playgroundParticles.skinnedWorldObject.normals.Length]));
								if (playgroundParticles.onlyLifetimePositioning) {
									playgroundParticles.playgroundCache.targetDirection[p] = fMx.MultiplyPoint3x4(Vector3Scale(playgroundParticles.lifetimePositioning.Evaluate(normalizedLife*lifetimePositioningTimeScale, playgroundParticles.lifetimePositioningScale), playgroundParticles.skinnedWorldObject.normals[p%playgroundParticles.skinnedWorldObject.normals.Length]));
									if (playgroundParticles.applyLifetimePositioningPositionScale)
										playgroundParticles.playgroundCache.targetDirection[p] *= playgroundParticles.lifetimePositioningPositionScale.Evaluate(normalizedLife);	
								}
								
								playgroundParticles.SetSourcePosition(p);
								
								// Local space compensation calculation
								if (playgroundParticles.localSpace && playgroundParticles.applyLocalSpaceMovementCompensation)
									playgroundParticles.playgroundCache.localSpaceMovementCompensation[p] = playgroundParticles.playgroundCache.targetPosition[p]-playgroundParticles.playgroundCache.previousTargetPosition[p];
							}
						}
						
						break;
					case SOURCEC.Projection:
						if (playgroundParticles.playgroundCache.rebirth[p] || playgroundParticles.onlySourcePositioning || playgroundParticles.onlyLifetimePositioning) {
							if (playgroundParticles.applyInitialLocalVelocity && !playgroundParticles.onlyLifetimePositioning)
								playgroundParticles.playgroundCache.targetDirection[p] = Vector3Scale(playgroundParticles.projection.GetNormal(p), playgroundParticles.playgroundCache.initialLocalVelocity[p]);
							if (playgroundParticles.onlyLifetimePositioning) {
								playgroundParticles.playgroundCache.targetDirection[p] = Vector3Scale(playgroundParticles.projection.GetNormal(p), playgroundParticles.lifetimePositioning.Evaluate(normalizedLife*lifetimePositioningTimeScale, playgroundParticles.lifetimePositioningScale));
								if (playgroundParticles.applyLifetimePositioningPositionScale)
									playgroundParticles.playgroundCache.targetDirection[p] *= playgroundParticles.lifetimePositioningPositionScale.Evaluate(normalizedLife);
							}
							
							playgroundParticles.SetSourcePosition(p);
						}
						
						break;
					case SOURCEC.Paint:
						if (playgroundParticles.playgroundCache.rebirth[p] || playgroundParticles.onlySourcePositioning || playgroundParticles.onlyLifetimePositioning) {
							if (playgroundParticles.applyInitialLocalVelocity && !playgroundParticles.onlyLifetimePositioning)
								playgroundParticles.playgroundCache.targetDirection[p] = playgroundParticles.paint.GetRotation(p)*Vector3Scale(playgroundParticles.playgroundCache.initialLocalVelocity[p], playgroundParticles.paint.GetNormal(p));
							if (playgroundParticles.onlyLifetimePositioning) {
								playgroundParticles.playgroundCache.targetDirection[p] = playgroundParticles.paint.GetRotation(p)*Vector3Scale(playgroundParticles.lifetimePositioning.Evaluate(normalizedLife*lifetimePositioningTimeScale, playgroundParticles.lifetimePositioningScale), playgroundParticles.paint.GetNormal(p));
								if (playgroundParticles.applyLifetimePositioningPositionScale)
									playgroundParticles.playgroundCache.targetDirection[p] *= playgroundParticles.lifetimePositioningPositionScale.Evaluate(normalizedLife);
							}
							
							playgroundParticles.SetSourcePosition(p);
							
							// Local space compensation calculation
							if (playgroundParticles.localSpace && playgroundParticles.applyLocalSpaceMovementCompensation) 
								playgroundParticles.playgroundCache.localSpaceMovementCompensation[p] = playgroundParticles.playgroundCache.targetPosition[p]-playgroundParticles.playgroundCache.previousTargetPosition[p];
						}
						break;
					case SOURCEC.Spline:
						if (playgroundParticles.playgroundCache.rebirth[p] || playgroundParticles.onlySourcePositioning || playgroundParticles.onlyLifetimePositioning) {
							if (playgroundParticles.treatAsOneSpline)
								playgroundParticles.splineIndex = (int)((((p*1f)/(pCount*1f))*playgroundParticles.splines.Count)+playgroundParticles.splineTimeOffset)%playgroundParticles.splines.Count;
							else
								playgroundParticles.splineIndex = p%playgroundParticles.splines.Count;
							
							float pSplineTime;
							if (playgroundParticles.treatAsOneSpline)
								pSplineTime = ((p*playgroundParticles.splines.Count*1f) / (pCount*1f))+playgroundParticles.splineTimeOffset;
							else
								pSplineTime = ((p*1f) / (pCount*1f)) + playgroundParticles.splineTimeOffset;
							
							if (playgroundParticles.applyInitialLocalVelocity && !playgroundParticles.onlyLifetimePositioning)
								playgroundParticles.playgroundCache.targetDirection[p] = Vector3Scale(playgroundParticles.splines[playgroundParticles.splineIndex].GetDirection(pSplineTime), playgroundParticles.playgroundCache.initialLocalVelocity[p]);
							if (playgroundParticles.onlyLifetimePositioning) {
								playgroundParticles.playgroundCache.targetDirection[p] = Vector3Scale(playgroundParticles.splines[playgroundParticles.splineIndex].GetDirection(pSplineTime), playgroundParticles.lifetimePositioning.Evaluate(normalizedLife*lifetimePositioningTimeScale, playgroundParticles.lifetimePositioningScale));
								if (playgroundParticles.applyLifetimePositioningPositionScale)
									playgroundParticles.playgroundCache.targetDirection[p] *= playgroundParticles.lifetimePositioningPositionScale.Evaluate(normalizedLife*lifetimePositioningTimeScale);
							}
							
							playgroundParticles.playgroundCache.targetPosition[p] = playgroundParticles.splines[playgroundParticles.splineIndex].GetPoint(pSplineTime);
							if (playgroundParticles.applySourceScatter)
								playgroundParticles.playgroundCache.targetPosition[p] += Vector3.Scale (playgroundParticles.playgroundCache.scatterPosition[p],playgroundParticles.scatterScale);
							
							// Local space compensation calculation
							if (playgroundParticles.localSpace && playgroundParticles.applyLocalSpaceMovementCompensation)
								playgroundParticles.playgroundCache.localSpaceMovementCompensation[p] = playgroundParticles.playgroundCache.targetPosition[p]-playgroundParticles.playgroundCache.previousTargetPosition[p];
						}
						break;
					}
				}
				
				// Set initial particle values if life is 0
				if (playgroundParticles.playgroundCache.life[p]==0) {
					if (!playgroundParticles.onlyLifetimePositioning) {
						playgroundParticles.playgroundCache.position[p] = playgroundParticles.playgroundCache.targetPosition[p];
						
						// Apply birth position delta
						if (playgroundParticles.applyDeltaOnRebirth && !playgroundParticles.cameFromNonEmissionFrame && playgroundParticles.localTime-playgroundParticles.emissionStopped > playgroundParticles.lifetime && playgroundParticles.playgroundCache.birthDelay[p]==0 && !playgroundParticles.onlySourcePositioning) {
							float timeDelta = playgroundParticles.localTime-playgroundParticles.playgroundCache.birth[p];
							if (playgroundParticles.isPrewarming) timeDelta *=.5f;
							playgroundParticles.playgroundCache.position[p] += playgroundParticles.playgroundCache.velocity[p]*playgroundParticles.velocityScale*timeDelta;
						}
					}
					playgroundParticles.playgroundCache.initialColor[p] = lifetimeColor;
					
					// Delta movement velocity
					if (!playgroundParticles.cameFromNonEmissionFrame && playgroundParticles.calculateDeltaMovement && !playgroundParticles.isPrewarming && playgroundParticles.source!=SOURCEC.Script) {
						Vector3 deltaVelocity = playgroundParticles.playgroundCache.targetPosition[p]-playgroundParticles.playgroundCache.previousTargetPosition[p];
						if (playgroundParticles.deltaMovementStrengthValueMethod == VALUEMETHOD.Constant)
							playgroundParticles.playgroundCache.velocity[p] += (deltaVelocity*playgroundParticles.deltaMovementStrength)/playgroundParticles.realSimulationTime;
						else
							playgroundParticles.playgroundCache.velocity[p] += (deltaVelocity*RandomRange(playgroundParticles.internalRandom01, playgroundParticles.deltaMovementStrength, playgroundParticles.minDeltaMovementStrength))/playgroundParticles.realSimulationTime;
					}
					
					playgroundParticles.playgroundCache.birthDelay[p] = 0;
				}
				
				if (playgroundParticles.playgroundCache.birth[p]>playgroundParticles.localTime) {
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
					playgroundParticles.particleCache[p].size = 0;
#else
					playgroundParticles.particleCache[p].startSize = 0;
#endif
					playgroundParticles.playgroundCache.position[p] = PlaygroundC.initialTargetPosition;
				}
				
				// Particle lifetime, velocity and manipulators
				if (playgroundParticles.playgroundCache.rebirth[p]) {
					
					// Particle is alive
					if (playgroundParticles.playgroundCache.birth[p]+playgroundParticles.playgroundCache.life[p]<=playgroundParticles.localTime+lifeInSeconds && (!playgroundParticles.playgroundCache.isNonBirthed[p] || playgroundParticles.onlyLifetimePositioning || playgroundParticles.onlySourcePositioning)) {
						
						// Lifetime size
						if (!playgroundParticles.playgroundCache.changedByPropertySize[p]) {
							if (playgroundParticles.applyLifetimeSize && !playgroundParticles.applyParticleArraySize)
								playgroundParticles.playgroundCache.size[p] = playgroundParticles.playgroundCache.initialSize[p]*playgroundParticles.lifetimeSize.Evaluate(normalizedLife)*playgroundParticles.scale;
							else if (playgroundParticles.applyLifetimeSize && playgroundParticles.applyParticleArraySize)
								playgroundParticles.playgroundCache.size[p] = playgroundParticles.playgroundCache.initialSize[p]*playgroundParticles.lifetimeSize.Evaluate(normalizedLife)*playgroundParticles.particleArraySize.Evaluate((p*1f)/(playgroundParticles.particleCount*1f))*playgroundParticles.scale;
							else if (playgroundParticles.applyParticleArraySize)
								playgroundParticles.playgroundCache.size[p] = playgroundParticles.playgroundCache.initialSize[p]*playgroundParticles.particleArraySize.Evaluate((p*1f)/(playgroundParticles.particleCount*1f))*playgroundParticles.scale;
							else playgroundParticles.playgroundCache.size[p] = playgroundParticles.playgroundCache.initialSize[p]*playgroundParticles.scale;
						}
						
						if (!playgroundParticles.onlySourcePositioning && !playgroundParticles.onlyLifetimePositioning) {
							
							// Check if particle has sticky collision
							if (playgroundParticles.hasCollisionCache && playgroundParticles.stickyCollisions && playgroundParticles.collisionCache.hasCollided[p] && !playgroundParticles.playgroundCache.isNonBirthed[p]) {
								if (playgroundParticles.stickyCollisionsSurfaceOffset==0)
									playgroundParticles.playgroundCache.position[p] = playgroundParticles.collisionCache.stickyPosition[p];
								else
									playgroundParticles.playgroundCache.position[p] = playgroundParticles.collisionCache.stickyPosition[p] + (playgroundParticles.collisionCache.collisionNormal[p]*playgroundParticles.stickyCollisionsSurfaceOffset);
							} else {
								
								if (!playgroundParticles.playgroundCache.noForce[p] && playgroundParticles.playgroundCache.life[p]>0) {
									
									// Velocity bending
									if (playgroundParticles.applyVelocityBending) {
										if (playgroundParticles.velocityBendingType==VELOCITYBENDINGTYPEC.SourcePosition) {
											playgroundParticles.playgroundCache.velocity[p] += Vector3.Reflect(
												new Vector3(
												playgroundParticles.playgroundCache.velocity[p].x*playgroundParticles.velocityBending.x,
												playgroundParticles.playgroundCache.velocity[p].y*playgroundParticles.velocityBending.y, 
												playgroundParticles.playgroundCache.velocity[p].z*playgroundParticles.velocityBending.z
												),
												(playgroundParticles.playgroundCache.targetPosition[p]-playgroundParticles.playgroundCache.position[p]).normalized
												)*t;
										} else {
											playgroundParticles.playgroundCache.velocity[p] += Vector3.Reflect(
												new Vector3(
												playgroundParticles.playgroundCache.velocity[p].x*playgroundParticles.velocityBending.x,
												playgroundParticles.playgroundCache.velocity[p].y*playgroundParticles.velocityBending.y, 
												playgroundParticles.playgroundCache.velocity[p].z*playgroundParticles.velocityBending.z
												),
												(playgroundParticles.playgroundCache.previousParticlePosition[p]-playgroundParticles.playgroundCache.position[p]).normalized
												)*t;
										}
									}
									
									// Set previous target position (used by delta velocity & local space movement compensation)
									playgroundParticles.playgroundCache.previousTargetPosition[p] = playgroundParticles.playgroundCache.targetPosition[p];
									
									// Gravity
									if (playgroundParticles.localSpace && playgroundParticles.source==SOURCEC.Transform && playgroundParticles.transformIndex!=playgroundParticles.psTransformNum)
										playgroundParticles.playgroundCache.velocity[p] -= playgroundParticles.sourceTransforms[playgroundParticles.transformIndex].rotation*playgroundParticles.gravity*t;
									else
										playgroundParticles.playgroundCache.velocity[p] -= playgroundParticles.gravity*t;
									
									// Lifetime additive velocity
									if (playgroundParticles.applyLifetimeVelocity) 
										playgroundParticles.playgroundCache.velocity[p] += playgroundParticles.lifetimeVelocity.Evaluate(normalizedLife, playgroundParticles.lifetimeVelocityScale)*t;
									
									// Turbulence inside the calculation loop
									if (playgroundParticles.HasTurbulence() && PlaygroundC.reference.turbulenceThreadMethod==ThreadMethodComponent.InsideParticleCalculation) {
										if (!playgroundParticles.playgroundCache.noForce[p])
											Turbulence(playgroundParticles, playgroundParticles.turbulenceSimplex, p, playgroundParticles.t, playgroundParticles.turbulenceType, playgroundParticles.turbulenceTimeScale, playgroundParticles.turbulenceScale/playgroundParticles.velocityScale, playgroundParticles.turbulenceStrength, playgroundParticles.turbulenceApplyLifetimeStrength, playgroundParticles.turbulenceLifetimeStrength);
									}
									
									// Damping, max velocity, constraints and final positioning
									
									// Max velocity
									if (playgroundParticles.playgroundCache.velocity[p].sqrMagnitude>playgroundParticles.maxVelocity)
										playgroundParticles.playgroundCache.velocity[p] = Vector3.ClampMagnitude(playgroundParticles.playgroundCache.velocity[p], playgroundParticles.maxVelocity);
									
									// Damping
									if (playgroundParticles.damping>0)
										playgroundParticles.playgroundCache.velocity[p] = Vector3.Lerp(playgroundParticles.playgroundCache.velocity[p], zero, playgroundParticles.damping*t);
									
									// Transition back to source
									if (playgroundParticles.transitionBackToSource) {
										float transitionAmount = playgroundParticles.transitionBackToSourceAmount.Evaluate(normalizedLife)*playgroundParticles.particleTimescale;
										playgroundParticles.playgroundCache.position[p] = Vector3.Lerp(playgroundParticles.playgroundCache.position[p], playgroundParticles.playgroundCache.targetPosition[p], transitionAmount);
										playgroundParticles.playgroundCache.velocity[p] *= 1f-transitionAmount;
									}
									
									// Axis constraints
									if (playgroundParticles.axisConstraints.x)
										playgroundParticles.playgroundCache.velocity[p].x = 0;
									if (playgroundParticles.axisConstraints.y)
										playgroundParticles.playgroundCache.velocity[p].y = 0;
									if (playgroundParticles.axisConstraints.z)
										playgroundParticles.playgroundCache.velocity[p].z = 0;
									
									
									// Set calculated collision position 
									playgroundParticles.playgroundCache.collisionParticlePosition[p] = playgroundParticles.playgroundCache.position[p];
									
									
									// Relocate
									playgroundParticles.playgroundCache.position[p] += (playgroundParticles.playgroundCache.velocity[p]*playgroundParticles.velocityScale)*t;
									if (playgroundParticles.localSpace && playgroundParticles.applyLocalSpaceMovementCompensation) {
										if (!playgroundParticles.applyMovementCompensationLifetimeStrength)
											playgroundParticles.playgroundCache.position[p] += playgroundParticles.playgroundCache.localSpaceMovementCompensation[p];
										else
											playgroundParticles.playgroundCache.position[p] += playgroundParticles.playgroundCache.localSpaceMovementCompensation[p]*playgroundParticles.movementCompensationLifetimeStrength.Evaluate(normalizedLife);
									}
									
									// Set particle velocity to be able to stretch towards movement
									if (playgroundParticles.renderModeStretch && playgroundParticles.realSimulationTime>0) {
										if (playgroundParticles.applyLifetimeStretching) {
											playgroundParticles.particleCache[p].velocity = Vector3.Slerp (playgroundParticles.particleCache[p].velocity, ((playgroundParticles.playgroundCache.position[p]-playgroundParticles.playgroundCache.previousParticlePosition[p])*playgroundParticles.stretchLifetime.Evaluate(playgroundParticles.playgroundCache.life[p]/lifeInSeconds))/playgroundParticles.realSimulationTime, t*playgroundParticles.stretchSpeed * playgroundParticles.realSimulationTime);
										} else {
											if (playgroundParticles.stretchSpeed>0)
												playgroundParticles.particleCache[p].velocity = Vector3.Slerp (playgroundParticles.particleCache[p].velocity, (playgroundParticles.playgroundCache.position[p]-playgroundParticles.playgroundCache.previousParticlePosition[p])/playgroundParticles.realSimulationTime, t*playgroundParticles.stretchSpeed * playgroundParticles.realSimulationTime);
											else playgroundParticles.particleCache[p].velocity = playgroundParticles.stretchStartDirection;
										}
									}
									
								}
							}
						} else {
							
							// Only Source Positioning / Lifetime Positioning
							
							if (playgroundParticles.onlyLifetimePositioning && !playgroundParticles.onlySourcePositioning) {
								if (!playgroundParticles.playgroundCache.changedByPropertyTarget[p]) {
									
									// Lifetime Positioning by Vector3 Animation Curve
									if (playgroundParticles.lifetimePositioningUsesSourceDirection && playgroundParticles.source!=SOURCEC.Script) {
										playgroundParticles.playgroundCache.position[p] = playgroundParticles.playgroundCache.targetPosition[p]+(playgroundParticles.playgroundCache.targetDirection[p]);
									} else {
										if (!playgroundParticles.applyLifetimePositioningPositionScale) {
											playgroundParticles.playgroundCache.position[p] = 
												playgroundParticles.playgroundCache.targetPosition[p]+
													playgroundParticles.lifetimePositioning.Evaluate(normalizedLife*lifetimePositioningTimeScale, playgroundParticles.lifetimePositioningScale);
										} else {
											playgroundParticles.playgroundCache.position[p] = 
												playgroundParticles.playgroundCache.targetPosition[p]+
													playgroundParticles.lifetimePositioning.Evaluate(normalizedLife*lifetimePositioningTimeScale, playgroundParticles.lifetimePositioningScale)*
													playgroundParticles.lifetimePositioningPositionScale.Evaluate(normalizedLife*lifetimePositioningTimeScale);
										}
									}
								}
							} else if (playgroundParticles.source!=SOURCEC.Script && !playgroundParticles.playgroundCache.isNonBirthed[p]) {
								playgroundParticles.playgroundCache.position[p] = playgroundParticles.playgroundCache.targetPosition[p];
							}
							
							// Set particle velocity to be able to stretch towards movement
							if (playgroundParticles.renderModeStretch && playgroundParticles.realSimulationTime>0) {
								if (playgroundParticles.applyLifetimeStretching) {
									playgroundParticles.particleCache[p].velocity = Vector3.Slerp (playgroundParticles.particleCache[p].velocity, (playgroundParticles.playgroundCache.position[p]-playgroundParticles.playgroundCache.previousParticlePosition[p])/playgroundParticles.realSimulationTime, t*playgroundParticles.stretchSpeed)*playgroundParticles.stretchLifetime.Evaluate(playgroundParticles.playgroundCache.life[p]/lifeInSeconds);
								} else {
									if (playgroundParticles.stretchSpeed>0)
										playgroundParticles.particleCache[p].velocity = Vector3.Slerp (playgroundParticles.particleCache[p].velocity, (playgroundParticles.playgroundCache.position[p]-playgroundParticles.playgroundCache.previousParticlePosition[p])/playgroundParticles.realSimulationTime, t*playgroundParticles.stretchSpeed);
									else playgroundParticles.particleCache[p].velocity = playgroundParticles.stretchStartDirection;
								}
							}
							
							playgroundParticles.playgroundCache.previousTargetPosition[p] = playgroundParticles.playgroundCache.targetPosition[p];
							
						}
						
						// Rotation
						if (t!=0) {
							if (!playgroundParticles.rotateTowardsDirection)
								playgroundParticles.playgroundCache.rotation[p] += playgroundParticles.playgroundCache.rotationSpeed[p]*t;
							else if (playgroundParticles.playgroundCache.life[p]!=0 && playgroundParticles.playgroundCache.position[p]-playgroundParticles.playgroundCache.previousParticlePosition[p]!=Vector3.zero) {
								playgroundParticles.playgroundCache.rotation[p] = playgroundParticles.playgroundCache.initialRotation[p]+SignedAngle(
									up, 
									playgroundParticles.playgroundCache.position[p]-playgroundParticles.playgroundCache.previousParticlePosition[p],
									playgroundParticles.rotationNormal
									);
							}
						}
						
						if (!playgroundParticles.syncPositionsOnMainThread && playgroundParticles.playgroundCache.life[p]>0)
							playgroundParticles.particleCache[p].rotation = playgroundParticles.playgroundCache.rotation[p];
						
						// Set previous particle position
						playgroundParticles.playgroundCache.previousParticlePosition[p] = playgroundParticles.playgroundCache.position[p];
						
						
						// Send timed event
						if (playgroundParticles.hasTimerEvent)
							playgroundParticles.SendEvent(EVENTTYPEC.Time, p);
					} else {
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
						playgroundParticles.particleCache[p].size = 0;
#else
						playgroundParticles.particleCache[p].startSize = 0;
#endif
						playgroundParticles.playgroundCache.position[p] = PlaygroundC.initialTargetPosition;
					}
					
					// Calculate lifetime
					float evaluatedLife = (playgroundParticles.localTime-playgroundParticles.playgroundCache.birth[p])/lifeInSeconds;
					
					// Lifetime
					if (playgroundParticles.playgroundCache.life[p]<playgroundParticles.playgroundCache.death[p]-playgroundParticles.playgroundCache.birth[p]) {
						playgroundParticles.playgroundCache.life[p] = lifeInSeconds*evaluatedLife;
						if (hasLifetimeLoss)
						{
							playgroundParticles.playgroundCache.life[p] += playgroundParticles.playgroundCache.lifetimeLoss[p];
							playgroundParticles.playgroundCache.lifetimeLoss[p] = 0;
						}
						if (!playgroundParticles.syncPositionsOnMainThread)
							playgroundParticles.particleCache[p].lifetime = Mathf.Clamp (lifeInSeconds*(1f-evaluatedLife), playgroundParticles.minShurikenLifetime, playgroundParticles.playgroundCache.death[p]-playgroundParticles.playgroundCache.birth[p]);
						
						if (playgroundParticles.lifetimeValueMethod==VALUEMETHOD.RandomBetweenTwoValues && playgroundParticles.playgroundCache.life[p]>lifeInSeconds) {
							
							// Send death event for particles with lifetime subtraction
							if ((playgroundParticles.hasEvent||playgroundParticles.hasEventManipulatorGlobal||playgroundParticles.hasEventManipulatorLocal) && !playgroundParticles.playgroundCache.isNonBirthed[p])
								SendDeathEvents(playgroundParticles, p);
							
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
							playgroundParticles.particleCache[p].size = 0;
#else
							playgroundParticles.particleCache[p].startSize = 0;
#endif
							playgroundParticles.particleCache[p].velocity = zero;
							playgroundParticles.playgroundCache.position[p] = PlaygroundC.initialTargetPosition;
							
						}
					} else {
						
						// Particle exceeded with death property
						if (!playgroundParticles.loop && !playgroundParticles.playgroundCache.isNonBirthed[p]) {
							
							// Send death event for particles which died of unnatural cause such as property death, the worst type of death
							if (playgroundParticles.hasEvent||playgroundParticles.hasEventManipulatorGlobal||playgroundParticles.hasEventManipulatorLocal)
								SendDeathEvents(playgroundParticles, p);
							
							playgroundParticles.InactivateParticle(p);
							continue;
						}
						
						// Loop exceeded normally
						if (!playgroundParticles.loop && playgroundParticles.localTime>playgroundParticles.simulationStarted+(playgroundParticles.playgroundCache.death[p]-playgroundParticles.playgroundCache.birth[p])-.01f) {
							playgroundParticles.loopExceeded = true;
							if (playgroundParticles.loopExceededOnParticle==p && evaluatedLife>2f) {
								if (playgroundParticles.disableOnDone)
									playgroundParticles.queueEmissionHalt = true;
								playgroundParticles.threadHadNoActiveParticles = true;
								playgroundParticles.hasActiveParticles = false;
							}
							if (playgroundParticles.loopExceededOnParticle==-1)
								playgroundParticles.loopExceededOnParticle = p;
						}
						
						playgroundParticles.particleCache[p].velocity = zero;
						
						// Send death event for particles with full lifetime length
						if ((playgroundParticles.hasEvent||playgroundParticles.hasEventManipulatorGlobal||playgroundParticles.hasEventManipulatorLocal) && !playgroundParticles.playgroundCache.isNonBirthed[p])
							SendDeathEvents(playgroundParticles, p);
						
						// New cycle begins
						if (playgroundParticles.localTime>=playgroundParticles.playgroundCache.birth[p]+playgroundParticles.playgroundCache.birthDelay[p] && !playgroundParticles.loopExceeded && playgroundParticles.source!=SOURCEC.Script && playgroundParticles.emit) {
							if (!playgroundParticles.playgroundCache.changedByPropertyDeath[p] || playgroundParticles.playgroundCache.changedByPropertyDeath[p] && playgroundParticles.localTime>playgroundParticles.playgroundCache.death[p]) {
								Rebirth(playgroundParticles, p, playgroundParticles.internalRandom01);
							} else {
								playgroundParticles.particleCache[p].velocity = zero;
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
								playgroundParticles.particleCache[p].size = 0;
#else
								playgroundParticles.particleCache[p].startSize = 0;
#endif
								playgroundParticles.playgroundCache.position[p] = PlaygroundC.initialTargetPosition;
							}
						} else {
							playgroundParticles.InactivateParticle(p);
							continue;
						}
						
					}
					
					// Local Manipulators
					for (int m = 0; m<playgroundParticles.manipulators.Count; m++) {
						CalculateManipulator(playgroundParticles, playgroundParticles.manipulators[m], p, t, playgroundParticles.playgroundCache.life[p], playgroundParticles.playgroundCache.position[p], (playgroundParticles.localSpace?playgroundParticles.manipulators[m].transform.localPosition:playgroundParticles.manipulators[m].transform.position)+playgroundParticles.manipulatorFix, playgroundParticles.localSpace);
					}
					
					// Global Manipulators
					if (playgroundParticles.hasGlobalAffectingManipulators) {
						for (int m = 0; m<PlaygroundC.reference.manipulators.Count; m++) {
							if ((PlaygroundC.reference.manipulators[m].affects.value & 1<<playgroundParticles.GetLayer())!=0)
								CalculateManipulator(playgroundParticles, PlaygroundC.reference.manipulators[m], p, t, playgroundParticles.playgroundCache.life[p], playgroundParticles.playgroundCache.position[p], (playgroundParticles.localSpace?PlaygroundC.reference.manipulators[m].transform.localPosition:PlaygroundC.reference.manipulators[m].transform.position)+playgroundParticles.manipulatorFix, playgroundParticles.localSpace);
						}
					}
					
					// Set particle size
					if (!playgroundParticles.syncPositionsOnMainThread)
					{
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
						playgroundParticles.particleCache[p].size = (playgroundParticles.playgroundCache.maskAlpha[p]>0&&playgroundParticles.particleCache[p].position.y!=initYpos)?playgroundParticles.playgroundCache.size[p]:0;
#else
						playgroundParticles.particleCache[p].startSize = (playgroundParticles.playgroundCache.maskAlpha[p]>0&&playgroundParticles.particleCache[p].position.y!=initYpos)?playgroundParticles.playgroundCache.size[p]:0;
#endif
					}
				} else {
					
					// Particle is set to not rebirth
					playgroundParticles.InactivateParticle(p);
				}
				
				// Set particle position if no sync
				if (!playgroundParticles.syncPositionsOnMainThread) {
					playgroundParticles.particleCache[p].position = playgroundParticles.playgroundCache.position[p];
				}
				
				// Particle got calculated
				playgroundParticles.playgroundCache.isCalculatedThisFrame[p] = true;
				
			}// <- Particle loop ends here
			
			// Reset for next frame
			if (playgroundParticles.isSettingParticleTime) playgroundParticles.threadHadNoActiveParticles = false;
			else playgroundParticles.threadHadNoActiveParticles = noActiveParticles && !playgroundParticles.emit || noActiveParticles && !playgroundParticles.loop;
			playgroundParticles.cameFromNonEmissionFrame = false;
			playgroundParticles.isDoneThread = true;
			
			// Turbulence calculated here when using PlaygroundC.turbulenceThreadMethod of ThreadMethodComponent.OnePerSystem
			if (playgroundParticles.HasTurbulence() && PlaygroundC.reference.turbulenceThreadMethod==ThreadMethodComponent.OnePerSystem) {
				PlaygroundC.RunAsync(()=>{
					for (int p = 0; p<playgroundParticles.particleCount; p++) {
						if (!playgroundParticles.playgroundCache.noForce[p])
							Turbulence(playgroundParticles, playgroundParticles.turbulenceSimplex, p, playgroundParticles.t, playgroundParticles.turbulenceType, playgroundParticles.turbulenceTimeScale, playgroundParticles.turbulenceScale/playgroundParticles.velocityScale, playgroundParticles.turbulenceStrength, playgroundParticles.turbulenceApplyLifetimeStrength, playgroundParticles.turbulenceLifetimeStrength);
					}
				});
			}
		}
		// Color all particles from lifetime span with sorting
		public static void SetColorWithLifetimeSorting (PlaygroundParticlesC playgroundParticles) {
			SetLifetime(playgroundParticles, playgroundParticles.sorting, playgroundParticles.lifetime);
			Color32 c;
			for (int p = 0; p<playgroundParticles.particleCount; p++) {
				c = playgroundParticles.lifetimeColor.Evaluate(playgroundParticles.playgroundCache.life[p]/playgroundParticles.lifetime);
				playgroundParticles.SetParticleColorInternal(p, c);
			}
			playgroundParticles.shurikenParticleSystem.SetParticles(playgroundParticles.particleCache, playgroundParticles.particleCache.Length);
		}
		// Color all particles from evaluated lifetime color value where time is normalized
		public static void SetColorAtLifetime (PlaygroundParticlesC playgroundParticles, float time) {
			Color32 c = playgroundParticles.lifetimeColor.Evaluate(time/playgroundParticles.lifetime);
			for (int p = 0; p<playgroundParticles.particleCount; p++)
				playgroundParticles.SetParticleColorInternal(p, c);
			playgroundParticles.shurikenParticleSystem.SetParticles(playgroundParticles.particleCache, playgroundParticles.particleCache.Length);
		}
		// Set alphas for particles
		public static void SetAlpha (PlaygroundParticlesC playgroundParticles, float alpha) {
			Color pColor;
			for (int i = 0; i<playgroundParticles.particleCache.Length; i++) {
				pColor = playgroundParticles.GetParticleColorInternal(i);
				pColor.a = alpha;
				playgroundParticles.SetParticleColorInternal(i, pColor);
			}
		}