private void FixedUpdate() { if (!Emit) { return; } var velocity = Part?.GetComponent <Rigidbody>().velocity ?? Rb.velocity; var originalLocalPosition = gameObject.transform.localPosition; var originalPosition = gameObject.transform.position; var startPosition = gameObject.transform.position + velocity * Time.fixedDeltaTime; var originalGapDistance = Vector3.Distance(originalPosition, startPosition); var intermediateSteps = originalGapDistance / MaxDistance; PEmitter.EmitParticle(); gameObject.transform.position = Vector3.MoveTowards( gameObject.transform.position, startPosition, MaxDistance); for (var i = 1; i < intermediateSteps; i++) { PEmitter.EmitParticle(); gameObject.transform.position = Vector3.MoveTowards( gameObject.transform.position, startPosition, MaxDistance); } gameObject.transform.localPosition = originalLocalPosition; }
void FixedUpdate() { if (!part && !rb) { internalVelocity = (transform.position - lastPos) / Time.fixedDeltaTime; lastPos = transform.position; if (emit && internalVelocity.sqrMagnitude > 562500) { return; //dont bridge gap if floating origin shifted } } if (emit) { maxDistance = Mathf.Clamp((pEmitter.minSize / 3), 0.3f, 5f) + (Mathf.Clamp((BDArmorySetup.numberOfParticleEmitters - 1), 0, 20) * 0.07f); Vector3 originalLocalPosition = gameObject.transform.localPosition; Vector3 originalPosition = gameObject.transform.position; Vector3 startPosition = gameObject.transform.position; if (useInternalV) { startPosition -= (velocity * Time.fixedDeltaTime); } else { startPosition += (velocity * Time.fixedDeltaTime); } float originalGapDistance = Vector3.Distance(originalPosition, startPosition); float intermediateSteps = originalGapDistance / maxDistance; pEmitter.EmitParticle(); gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, startPosition, maxDistance); for (int i = 1; i < intermediateSteps; i++) { pEmitter.EmitParticle(); gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, startPosition, maxDistance); } gameObject.transform.localPosition = originalLocalPosition; } }
void FixedUpdate() { if (emit) { Vector3 velocity = (part == null) ? rb.velocity : part.rigidbody.velocity; Vector3 originalLocalPosition = gameObject.transform.localPosition; Vector3 originalPosition = gameObject.transform.position; Vector3 startPosition = gameObject.transform.position + (velocity * Time.fixedDeltaTime); float originalGapDistance = Vector3.Distance(originalPosition, startPosition); float intermediateSteps = originalGapDistance / maxDistance; pEmitter.EmitParticle(); gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, startPosition, maxDistance); for (int i = 1; i < intermediateSteps; i++) { pEmitter.EmitParticle(); gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, startPosition, maxDistance); } gameObject.transform.localPosition = originalLocalPosition; } }
private void FixedUpdate() { if (!part && !rb) { internalVelocity = (transform.position - lastPos) / Time.fixedDeltaTime; lastPos = transform.position; if (PEmitter.emit && internalVelocity.sqrMagnitude > 562500) { return; //dont bridge gap if floating origin shifted } } if (!Emit) { return; } //var velocity = part?.GetComponent<Rigidbody>().velocity ?? rb.velocity; var originalLocalPosition = gameObject.transform.localPosition; var originalPosition = gameObject.transform.position; var startPosition = gameObject.transform.position + velocity * Time.fixedDeltaTime; var originalGapDistance = Vector3.Distance(originalPosition, startPosition); var intermediateSteps = originalGapDistance / MaxDistance; PEmitter.EmitParticle(); gameObject.transform.position = Vector3.MoveTowards( gameObject.transform.position, startPosition, MaxDistance); for (var i = 1; i < intermediateSteps; i++) { PEmitter.EmitParticle(); gameObject.transform.position = Vector3.MoveTowards( gameObject.transform.position, startPosition, MaxDistance); } gameObject.transform.localPosition = originalLocalPosition; }
IEnumerator LifeRoutine() { geoPos = VectorUtils.WorldPositionToGeoCoords(transform.position, body); pe.EmitParticle(); float startTime = Time.time; while (Time.time - startTime < pe.maxEnergy) { transform.position = body.GetWorldSurfacePosition(geoPos.x, geoPos.y, geoPos.z); velocity += FlightGlobals.getGeeForceAtPosition(transform.position) * Time.fixedDeltaTime; Vector3 dragForce = (0.008f) * drag * 0.5f * velocity.sqrMagnitude * (float)FlightGlobals.getAtmDensity(FlightGlobals.getStaticPressure(transform.position), FlightGlobals.getExternalTemperature(), body) * velocity.normalized; velocity -= (dragForce) * Time.fixedDeltaTime; transform.position += velocity * Time.fixedDeltaTime; geoPos = VectorUtils.WorldPositionToGeoCoords(transform.position, body); yield return(new WaitForFixedUpdate()); } gameObject.SetActive(false); }
// Update the particles of the Emitter : Emit, resize, collision and physic public void EmitterOnUpdate(Vector3 emitterWorldVelocity) { // "Default", "TransparentFX", "Local Scenery", "Ignore Raycast" int mask = (1 << LayerMask.NameToLayer("Default")) | (1 << LayerMask.NameToLayer("Local Scenery")); // Emit particles on fixedUpdate rather than Update so that we know which particles // were just created and should be nudged, should not be collided, etc. if (fixedEmit) { // Number of particles to emit: double averageEmittedParticles = Random.Range(pe.minEmission, pe.maxEmission) * TimeWarp.fixedDeltaTime; double compensatedEmittedParticles = averageEmittedParticles + particleFraction; double emittedParticles = Math.Truncate(compensatedEmittedParticles); particleFraction = compensatedEmittedParticles - emittedParticles; int emissionCount = (int)emittedParticles; for (int k = 0; k < emissionCount; ++k) { pe.EmitParticle(); } } // This line (and the one that does the oposite at the end) is actally the slowest part of the whole function Particle[] particles = pe.pe.particles; double averageSize = 0.5 * (pe.minSize + pe.maxSize); //For randConeEmit: //Only generate a random vector on every other particle, for the in-between particles, negate the disk. bool toggle = true; Vector2 disk = new Vector2(0, 0); //For startSpread double logGrowConst = TimeWarp.fixedDeltaTime * logarithmicGrow * logarithmicGrowScale; float linGrowConst = (float)(TimeWarp.fixedDeltaTime * linearGrow * averageSize); Transform peTransform = pe.transform; Vector3d frameVel = Krakensbane.GetFrameVelocity(); //Step through all the particles: for (int j = 0; j < particles.Length; j++) { Particle particle = particles[j]; // Check if we need to cull the number of particles if (SmokeScreenConfig.particleDecimate != 0 && particles.Length > SmokeScreenConfig.decimateFloor) { SmokeScreenConfig.particleCounter++; if ((SmokeScreenConfig.particleDecimate > 0 && (SmokeScreenConfig.particleCounter % SmokeScreenConfig.particleDecimate) == 0) || (SmokeScreenConfig.particleDecimate < 0 && (SmokeScreenConfig.particleCounter % SmokeScreenConfig.particleDecimate) != 0)) { particle.energy = 0; // energy set to 0 remove the particle, as per Unity doc } } if (particle.energy > 0) { //Slight methodology change to avoid duplicating if statements: Vector3d pVel; Vector3d pPos; if (pe.useWorldSpace) { pVel = particle.velocity + frameVel; pPos = particle.position; } else if (!pe.useWorldSpace && particle.energy == particle.startEnergy) { Vector3 lVel = new Vector3(0, 0, 1); Vector3 lPos = particle.position; // Adjust initial velocity to make a cone. Only perform if pe.useWorldSpace // is true, and we have a randConeEmit set. //Produce a random vector within "angle" of the original vector. //The maximum producible cone is 90 degrees when randConeEmit is very large. //Could open up more if we used trig, but it'd be less efficient. if (toggle) { disk = Random.insideUnitCircle * randConeEmit; toggle = false; } else { disk *= -1; toggle = true; } lVel.x = disk.x; lVel.y = disk.y; lVel = Vector3.Normalize(lVel); lVel *= Vector3.Magnitude(particle.velocity); //Adjust initial position back along its position, if required. //Apply a random offset if vRandOffset != 0, else apply zero. float randoff = (vRandPosOffset != 0)? Random.Range(0, vRandPosOffset) : 0; lPos += Vector3.Normalize(lVel) * (randoff + vPosOffset); //Finalize position and velocity pPos = peTransform.TransformPoint(lPos); pVel = peTransform.TransformDirection(lVel) + frameVel; } else if (!pe.useWorldSpace && particle.energy != particle.startEnergy) { pPos = peTransform.TransformPoint(particle.position); pVel = peTransform.TransformDirection(particle.velocity.x * xyForce, particle.velocity.y * xyForce, particle.velocity.z * zForce) + frameVel; } else { pPos = peTransform.TransformPoint(particle.position); pVel = peTransform.TransformDirection(particle.velocity) + frameVel; } // try-finally block to ensure we set the particle velocities correctly in the end. try { // Fixed update is not the best place to update the size but the particles array copy is // slow so doing each frame would be worse // No need to waste time doing a division if the result is 0. if (logarithmicGrow != 0.0) { // Euler integration of the derivative of Log(logarithmicGrowth * t + 1) + 1. // This might look weird. particle.size += (float)((logGrowConst / (1 + (particle.startEnergy - particle.energy) * logarithmicGrow)) * averageSize); } if (linearGrow != 0.0) { particle.size += linGrowConst; } particle.size = Mathf.Min(particle.size, sizeClamp); if (particle.energy == particle.startEnergy) { if (pe.useWorldSpace) { // Uniformly scatter newly emitted particles along the emitter's trajectory in order to // remove the dotted smoke effect. // use variableDeltaTime since the particle are emited on Update anyway. pPos -= emitterWorldVelocity * Random.value * Time.deltaTime; } if (randomInitalVelocityOffsetMaxRadius != 0.0) { Vector2 diskPoint = Random.insideUnitCircle * randomInitalVelocityOffsetMaxRadius; Vector3d offset; if (pVel.x == 0.0 && pVel.y == 0.0) { offset = new Vector3d(diskPoint.x, diskPoint.y, 0.0); } else { // Convoluted calculations to save some operations (especially divisions). // Not that it really matters, but this achieves 2 divisions and 1 square root. double x = pVel.x; double y = pVel.y; double z = pVel.z; double xSquared = x * x; double ySquared = y * y; double xySquareNorm = xSquared + ySquared; double inverseXYSquareNorm = 1 / xySquareNorm; double inverseNorm = 1 / Math.Sqrt(xySquareNorm + z * z); double zOverNorm = z * inverseNorm; // TODO(robin): find an identifier for that... double mixedTerm = x * y * (zOverNorm - 1); offset = new Vector3d( ((ySquared + xSquared * zOverNorm) * diskPoint.x + mixedTerm * diskPoint.y) * inverseXYSquareNorm, ((xSquared + ySquared * zOverNorm) * diskPoint.y + mixedTerm * diskPoint.x) * inverseXYSquareNorm, -(x * diskPoint.x + y * diskPoint.y) * inverseNorm); } pVel += offset; } } if (physical && (j % physicsPass == activePhysicsPass)) { // There must be a way to keep the actual initial volume, // but I'm lazy. pVel = ParticlePhysics(particle.size, averageSize, pPos, pVel); } if (collide && particle.energy != particle.startEnergy // Do not collide newly created particles (they collide with the emitter and things look bad). && (j % physicsPass == activePhysicsPass)) { pVel = ParticleCollision(pPos, pVel, mask); } } finally { particle.velocity = (pe.useWorldSpace ? (Vector3)(pVel - frameVel) : peTransform.InverseTransformDirection(pVel - frameVel)); particle.position = pe.useWorldSpace ? (Vector3)pPos : peTransform.InverseTransformPoint(pPos); } } particles[j] = particle; } activePhysicsPass = ++activePhysicsPass % physicsPass; pe.pe.particles = particles; SmokeScreenConfig.activeParticles += pe.pe.particleCount; }