public static void InitEmitterConeSource(EntityManager mgr, Entity emitter, NativeArray <Entity> particles, bool attachToEmitter) { var source = mgr.GetComponentData <EmitterConeSource>(emitter); float3 localPositionOnConeBase; quaternion rotation = quaternion.identity; if (!attachToEmitter) { if (mgr.HasComponent <LocalToWorld>(emitter)) { var toWorld = mgr.GetComponentData <LocalToWorld>(emitter); rotation = new quaternion(toWorld.Value); } } foreach (var particle in particles) { float angle = m_rand.NextFloat((float)-math.PI, (float)math.PI); float radiusNormalized = math.sqrt(m_rand.NextFloat(0.0f, 1.0f)); float radius = source.radius * radiusNormalized; localPositionOnConeBase.x = math.sin(angle); localPositionOnConeBase.z = math.cos(angle); localPositionOnConeBase.y = 0.0f; var worldPositionOnConeBase = math.rotate(rotation, localPositionOnConeBase); var Translation = mgr.GetComponentData <Translation>(particle); Translation.Value += worldPositionOnConeBase * radius; mgr.SetComponentData(particle, Translation); ParticleVelocity particleVelocity = new ParticleVelocity(); float spreadAngle = source.angle * radiusNormalized; float directionRadius = math.sin(spreadAngle); float directionHeight = math.cos(spreadAngle); particleVelocity.velocity.x = localPositionOnConeBase.x * directionRadius; particleVelocity.velocity.z = localPositionOnConeBase.z * directionRadius; particleVelocity.velocity.y = directionHeight; particleVelocity.velocity *= source.speed; particleVelocity.velocity = math.rotate(rotation, particleVelocity.velocity); if (mgr.HasComponent <ParticleVelocity>(particle)) { mgr.SetComponentData(particle, particleVelocity); } else { mgr.AddComponentData(particle, particleVelocity); } } }
public static void InitEmitterCircleSource(EntityManager mgr, Entity emitter, NativeArray <Entity> particles) { var source = mgr.GetComponentData <EmitterCircleSource>(emitter); foreach (var particle in particles) { float randomAngle = m_rand.NextFloat((float)-math.PI, (float)math.PI); float radiusNormalized = source.radius.end != 0.0f ? math.sqrt(m_rand.NextFloat(source.radius.start / source.radius.end, 1.0f)) : 0.0f; float randomRadius = radiusNormalized * source.radius.end; var positionNormalized = new float2(math.sin(randomAngle), math.cos(randomAngle)); var position = new float3(positionNormalized.x * randomRadius, positionNormalized.y * randomRadius, 0.0f); var Translation = mgr.GetComponentData <Translation>(particle); Translation.Value += position; mgr.SetComponentData(particle, Translation); if (source.speed.start != 0.0f && source.speed.end != 0.0f) { float randomSpeed = m_rand.NextFloat(source.speed.start, source.speed.end); if (source.speedBasedOnRadius) { randomSpeed *= radiusNormalized; } var particleVelocity = new ParticleVelocity() { velocity = new float3(positionNormalized.x * randomSpeed, positionNormalized.y * randomSpeed, 0.0f) }; if (mgr.HasComponent <ParticleVelocity>(particle)) { mgr.SetComponentData(particle, particleVelocity); } else { mgr.AddComponentData(particle, particleVelocity); } } } }
private void SpawnParticles(EntityManager mgr, float deltaTime, Entity emitter) { var particleEmitter = mgr.GetComponentData <ParticleEmitter>(emitter); var particleEmitterInternal = mgr.GetComponentData <ParticleEmitterInternal>(emitter); uint particlesToSpawn = 0; if (mgr.HasComponent <BurstEmissionInternal>(emitter) && mgr.HasComponent <BurstEmission>(emitter)) { // Burst emission mode. var burstEmission = mgr.GetComponentData <BurstEmission>(emitter); var burstEmissionInternal = mgr.GetComponentData <BurstEmissionInternal>(emitter); if (burstEmissionInternal.cycle < burstEmission.cycles) { burstEmissionInternal.cooldown -= deltaTime; if (burstEmissionInternal.cooldown < 0.0f) { particlesToSpawn = (uint)m_rand.NextInt((int)burstEmission.count.start, (int)burstEmission.count.end); burstEmissionInternal.cycle++; burstEmissionInternal.cooldown = m_rand.NextFloat(burstEmission.interval.start, burstEmission.interval.end); } mgr.SetComponentData(emitter, burstEmissionInternal); } } else { // Normal emission mode. if (particleEmitter.emitRate > 0.0f) { particleEmitterInternal.particleSpawnCooldown += deltaTime; float particleSpawnDelay = 1.0f / particleEmitter.emitRate; particlesToSpawn = (uint)(particleEmitterInternal.particleSpawnCooldown / particleSpawnDelay); if (particlesToSpawn > 0) { particleEmitterInternal.particleSpawnCooldown -= particleSpawnDelay * particlesToSpawn; uint maxParticlesToSpawn = particleEmitter.maxParticles - particleEmitterInternal.numParticles; if (particlesToSpawn > maxParticlesToSpawn) { particlesToSpawn = maxParticlesToSpawn; } } mgr.SetComponentData(emitter, particleEmitterInternal); } } if (particlesToSpawn == 0) { return; } var newParticles = new NativeArray <Entity>((int)particlesToSpawn, Collections.Allocator.Persistent); // Before the new particles will spawn, Disabled component needs to be removed from the template particle. mgr.RemoveComponent <Disabled>(particleEmitterInternal.particleTemplate); mgr.Instantiate(particleEmitterInternal.particleTemplate, newParticles); mgr.AddComponentData(particleEmitterInternal.particleTemplate, new Disabled()); InitTime(mgr, deltaTime, particleEmitter.lifetime, newParticles); if (particleEmitter.attachToEmitter) { foreach (var particle in newParticles) { var node = new Parent() { Value = emitter }; if (mgr.HasComponent <Parent>(particle)) { mgr.SetComponentData(particle, node); } else { mgr.AddComponentData(particle, node); } var position = mgr.GetComponentData <Translation>(particle); position.Value = float3.zero; mgr.SetComponentData(particle, position); } } else { if (mgr.HasComponent <LocalToWorld>(emitter)) { var toWorld = mgr.GetComponentData <LocalToWorld>(emitter); var emitterWorldPos = new float3(toWorld.Value[3][0], toWorld.Value[3][1], toWorld.Value[3][2]); foreach (var particle in newParticles) { var localPos = mgr.GetComponentData <Translation>(particle); localPos.Value = emitterWorldPos; mgr.SetComponentData(particle, localPos); } } } if (mgr.HasComponent <EmitterInitialVelocity>(emitter)) { var velocity = mgr.GetComponentData <EmitterInitialVelocity>(emitter).velocity; var particleVelocity = new ParticleVelocity(); foreach (var particle in newParticles) { particleVelocity.velocity = velocity; mgr.AddComponentData(particle, particleVelocity); } } else if (mgr.HasComponent <LifetimeVelocity>(emitter)) { foreach (var particle in newParticles) { mgr.AddComponentData(particle, new ParticleVelocity() { velocity = float3.zero }); } } InitScale(mgr, emitter, newParticles); InitColor(mgr, emitter, newParticles); InitRotation(mgr, emitter, newParticles); // Init particle's position and the velocity based on the source. if (mgr.HasComponent <EmitterBoxSource>(emitter)) { ParticlesSource.InitEmitterBoxSource(mgr, emitter, newParticles); } else if (mgr.HasComponent <EmitterCircleSource>(emitter)) { ParticlesSource.InitEmitterCircleSource(mgr, emitter, newParticles); } else if (mgr.HasComponent <EmitterConeSource>(emitter)) { ParticlesSource.InitEmitterConeSource(mgr, emitter, newParticles, particleEmitter.attachToEmitter); } newParticles.Dispose(); }