protected virtual void AdvanceParticle(ParticleVO aParticle, float passedTime) { PDParticle particle = aParticle as PDParticle; float restTime = particle.totalTime - particle.currentTime; passedTime = restTime > passedTime ? passedTime : restTime; particle.currentTime += passedTime; if (m_particleConfigVO.emitterType == EmitterType.RADIAL) { particle.emitRotation += particle.emitRotationDelta * passedTime; particle.emitRadius += particle.emitRadiusDelta * passedTime; particle.x = emitterX - Mathf.Cos(particle.emitRotation) * particle.emitRadius; particle.y = emitterY - Mathf.Sin(particle.emitRotation) * particle.emitRadius; } else { float distanceX = particle.x - particle.startX; float distanceY = particle.y - particle.startY; float distanceScalar = Mathf.Sqrt(distanceX * distanceX + distanceY * distanceY); if (distanceScalar < 0.01f) { distanceScalar = 0.01f; } float radialX = distanceX / distanceScalar; float radialY = distanceY / distanceScalar; float tangentialX = radialX; float tangentialY = radialY; radialX *= particle.radialAcceleration; radialY *= particle.radialAcceleration; float newY = tangentialX; tangentialX = -tangentialY * particle.tangentialAcceleration; tangentialY = newY * particle.tangentialAcceleration; particle.velocityX += passedTime * (m_particleConfigVO.gravityX + radialX + tangentialX); particle.velocityY += passedTime * (m_particleConfigVO.gravityY + radialY + tangentialY); particle.x += particle.velocityX * passedTime; particle.y += particle.velocityY * passedTime; } particle.scale += particle.scaleDelta * passedTime; particle.rotation += particle.rotationDelta * passedTime; particle.colorArgb.r += particle.colorArgbDelta.r * passedTime; particle.colorArgb.g += particle.colorArgbDelta.g * passedTime; particle.colorArgb.b += particle.colorArgbDelta.b * passedTime; particle.colorArgb.a += particle.colorArgbDelta.a * passedTime; particle.color = particle.colorArgb; }
public void AdvanceTime(float passedTime) { int particleIndex = 0; ParticleVO particle; int maxNumParticles = capacity; // advance existing particles while (particleIndex < m_NumParticles) { particle = m_Particles[particleIndex]; if (particle.currentTime < particle.totalTime) { AdvanceParticle(particle, passedTime); ++particleIndex; } else { if (particleIndex != m_NumParticles - 1) { ParticleVO nextParticle = m_Particles[m_NumParticles - 1]; m_Particles[m_NumParticles - 1] = particle; m_Particles[particleIndex] = nextParticle; int id = (m_NumParticles - 1) * 4; SetVertex(id, 0, 0); SetVertex(id + 1, 0, 0); SetVertex(id + 2, 0, 0); SetVertex(id + 3, 0, 0); } --m_NumParticles; if (m_NumParticles == 0 && emissionTime == 0 && OnComplete != null) { OnComplete(); } } } // create and advance new particles if (emissionTime > 0) { float timeBetweenParticles = 1.0f / emissionRate; m_FrameTime += passedTime; while (m_FrameTime > 0) { if (m_NumParticles < maxNumParticles) { particle = m_Particles[m_NumParticles]; InitParticle(particle); // particle might be dead at birth if (particle.totalTime > 0.0f) { AdvanceParticle(particle, m_FrameTime); ++m_NumParticles; } } m_FrameTime -= timeBetweenParticles; } if (emissionTime != float.MaxValue) { emissionTime = emissionTime > passedTime ? emissionTime - passedTime : 0.0f; } if (m_NumParticles == 0 && emissionTime == 0 && OnComplete != null) { OnComplete(); } } // update vertex data int vertexID = 0; float rotation; float x, y; float offsetX, offsetY; float pivotX = textureWidth * 0.5f; float pivotY = textureHeight * 0.5f; Vector3 offset = Vector3.zero; if (m_transform != null && (simulationSpace == Space.World && m_particleConfigVO.emitterType != EmitterType.RADIAL)) { offset = m_transform.InverseTransformPoint(Vector3.zero); } Color c; for (int i = 0; i < m_NumParticles; ++i) { vertexID = i * 4; particle = m_Particles[i]; rotation = particle.rotation; offsetX = pivotX * particle.scale; offsetY = pivotY * particle.scale; x = particle.x + offset.x; y = particle.y + offset.y; c = particle.color; c.r *= color.r; c.g *= color.g; c.b *= color.b; c.a *= color.a; if (m_particleConfigVO.enableLifeColor && particle.totalTime > 0f) { float ts = particle.currentTime / particle.totalTime; Color lc = m_particleConfigVO.lifeColors.Evaluate(ts); c.r *= lc.r; c.g *= lc.g; c.b *= lc.b; c.a *= lc.a; } m_Colors[vertexID] = c; m_Colors[vertexID + 1] = c; m_Colors[vertexID + 2] = c; m_Colors[vertexID + 3] = c; if (rotation != 0f) { float cos = Mathf.Cos(rotation); float sin = Mathf.Sin(rotation); float cosX = cos * offsetX; float cosY = cos * offsetY; float sinX = sin * offsetX; float sinY = sin * offsetY; SetVertex(vertexID, x - cosX - sinY, y - sinX + cosY); SetVertex(vertexID + 1, x - cosX + sinY, y - sinX - cosY); SetVertex(vertexID + 2, x + cosX + sinY, y + sinX - cosY); SetVertex(vertexID + 3, x + cosX - sinY, y + sinX + cosY); } else { // optimization for rotation == 0 SetVertex(vertexID, x - offsetX, y + offsetY); SetVertex(vertexID + 1, x - offsetX, y - offsetY); SetVertex(vertexID + 2, x + offsetX, y - offsetY); SetVertex(vertexID + 3, x + offsetX, y + offsetY); } } //update dead particle if (m_NumParticles > 0) { if (emissionTime == 0f) { for (int i = m_NumParticles; i < m_Capacity; ++i) { vertexID = i * 4; SetVertex(vertexID, 0, 0); SetVertex(vertexID + 1, 0, 0); SetVertex(vertexID + 2, 0, 0); SetVertex(vertexID + 3, 0, 0); } } m_Mesh.vertices = m_Vertices; m_Mesh.colors32 = m_Colors; m_bounds.center = m_transform.position; m_Mesh.bounds = m_bounds; m_isOver = false; } else { m_isOver = true; } }
protected virtual void InitParticle(ParticleVO aParticle) { PDParticle particle = aParticle as PDParticle; // for performance reasons, the random variances are calculated inline instead // of calling a function float lifespan = m_particleConfigVO.lifespan + m_particleConfigVO.lifespanVariance * (Random.value * 2.0f - 1.0f); particle.currentTime = 0.0f; particle.totalTime = lifespan > 0.0f ? lifespan : 0.0f; if (lifespan <= 0.0f) { return; } float emitterX = this.emitterX; float emitterY = this.emitterY; if (m_transform != null && (simulationSpace == Space.World && m_particleConfigVO.emitterType != EmitterType.RADIAL)) { Vector2 help = m_transform.InverseTransformPoint(emitterX, emitterY, 0); emitterX = -help.x; emitterY = -help.y; } particle.x = emitterX + m_particleConfigVO.emitterXVariance * (Random.value * 2.0f - 1.0f); particle.y = emitterY + m_particleConfigVO.emitterYVariance * (Random.value * 2.0f - 1.0f); particle.startX = emitterX; particle.startY = emitterY; float angle = m_particleConfigVO.emitAngle + m_particleConfigVO.emitAngleVariance * (Random.value * 2.0f - 1.0f); float speed = m_particleConfigVO.speed + m_particleConfigVO.speedVariance * (Random.value * 2.0f - 1.0f); particle.velocityX = speed * Mathf.Cos(angle); particle.velocityY = speed * Mathf.Sin(angle); float startRadius = m_particleConfigVO.maxRadius + m_particleConfigVO.maxRadiusVariance * (Random.value * 2.0f - 1.0f); float endRadius = m_particleConfigVO.minRadius + m_particleConfigVO.minRadiusVariance * (Random.value * 2.0f - 1.0f); particle.emitRadius = startRadius; particle.emitRadiusDelta = (endRadius - startRadius) / lifespan; particle.emitRotation = m_particleConfigVO.emitAngle + m_particleConfigVO.emitAngleVariance * (Random.value * 2.0f - 1.0f); particle.emitRotationDelta = m_particleConfigVO.rotatePerSecond + m_particleConfigVO.rotatePerSecondVariance * (Random.value * 2.0f - 1.0f); particle.radialAcceleration = m_particleConfigVO.radialAcceleration + m_particleConfigVO.radialAccelerationVariance * (Random.value * 2.0f - 1.0f); particle.tangentialAcceleration = m_particleConfigVO.tangentialAcceleration + m_particleConfigVO.tangentialAccelerationVariance * (Random.value * 2.0f - 1.0f); float startSize = m_particleConfigVO.startSize + m_particleConfigVO.startSizeVariance * (Random.value * 2.0f - 1.0f); float endSize = m_particleConfigVO.endSize + m_particleConfigVO.endSizeVariance * (Random.value * 2.0f - 1.0f); if (startSize < 0.1f) { startSize = 0.1f; } if (endSize < 0.1f) { endSize = 0.1f; } if (m_particleConfigVO != null && m_particleConfigVO.texture != null) { particle.scale = startSize / textureWidth; particle.scaleDelta = ((endSize - startSize) / lifespan) / textureWidth; } else { particle.scale = 1f; particle.scaleDelta = 0f; } // colors Color startColor = particle.colorArgb; Color colorDelta = particle.colorArgbDelta; startColor.r = m_particleConfigVO.startColor.r; startColor.g = m_particleConfigVO.startColor.g; startColor.b = m_particleConfigVO.startColor.b; startColor.a = m_particleConfigVO.startColor.a; if (m_particleConfigVO.startColorVariance.r != 0) { startColor.r += m_particleConfigVO.startColorVariance.r * (Random.value * 2.0f - 1.0f); } if (m_particleConfigVO.startColorVariance.g != 0) { startColor.g += m_particleConfigVO.startColorVariance.g * (Random.value * 2.0f - 1.0f); } if (m_particleConfigVO.startColorVariance.b != 0) { startColor.b += m_particleConfigVO.startColorVariance.b * (Random.value * 2.0f - 1.0f); } if (m_particleConfigVO.startColorVariance.a != 0) { startColor.a += m_particleConfigVO.startColorVariance.a * (Random.value * 2.0f - 1.0f); } particle.colorArgb = startColor; float endColorRed = m_particleConfigVO.endColor.r; float endColorGreen = m_particleConfigVO.endColor.g; float endColorBlue = m_particleConfigVO.endColor.b; float endColorAlpha = m_particleConfigVO.endColor.a; if (m_particleConfigVO.endColorVariance.r != 0) { endColorRed += m_particleConfigVO.endColorVariance.r * (Random.value * 2.0f - 1.0f); } if (m_particleConfigVO.endColorVariance.g != 0) { endColorGreen += m_particleConfigVO.endColorVariance.g * (Random.value * 2.0f - 1.0f); } if (m_particleConfigVO.endColorVariance.b != 0) { endColorBlue += m_particleConfigVO.endColorVariance.b * (Random.value * 2.0f - 1.0f); } if (m_particleConfigVO.endColorVariance.a != 0) { endColorAlpha += m_particleConfigVO.endColorVariance.a * (Random.value * 2.0f - 1.0f); } colorDelta.r = (endColorRed - startColor.r) / lifespan; colorDelta.g = (endColorGreen - startColor.g) / lifespan; colorDelta.b = (endColorBlue - startColor.b) / lifespan; colorDelta.a = (endColorAlpha - startColor.a) / lifespan; particle.colorArgbDelta = colorDelta; // rotation float startRotation = m_particleConfigVO.startRotation + m_particleConfigVO.startRotationVariance * (Random.value * 2.0f - 1.0f); float endRotation = m_particleConfigVO.endRotation + m_particleConfigVO.endRotationVariance * (Random.value * 2.0f - 1.0f); particle.rotation = startRotation; if (m_particleConfigVO.enableEndRotation) { particle.rotationDelta = (endRotation - startRotation) / lifespan; } else { particle.rotationDelta = 0f; } }