Destroy Individual Particle?

Hiya

Is it possible to destroy an individual particle? Say I collide with a particle, is it possible to destroy that particle and ONLY that particle, not stop the whole emitter emitting…

something like this (though obviously this doesn’t work because of… oh a whole bunch of reasons :))

function OnParticleCollision(other : Particle){
Destroy (other)
}

I found a couple of link… may be that gives you a clue.

See the documentation:
http://unity3d.com/support/documentation/ScriptReference/ParticleEmitter.html

ParticleEmitter has “particles” variable, which returns a copy of all particles and assigns an array of all particles to be the current particles.

Wathc this:
http://unity3d.com/support/documentation/ScriptReference/ParticleEmitter-particles.html

Thanks, good find. I guess i can go through the array and find the one i’ve collided with… wish me luck :slight_smile:

Something like this maybe? Any pointers appreciated.

attached to Particle Emitter:

function RemoveParticle (theParticle) {
print ("Removing Particle");
// extract the particles
var particles = particleEmitter.particles;
for (var i=0; i<particles.Length; i++) {

if (i==theParticle){
particles.RemoveAt(i);
}

}
// copy them back to the particle system
particleEmitter.particles = particles;
}

then attached to the object that’s colliding with the particle emitter:

function OnParticleCollision(other : GameObject){
var theParticle = Particle;
other.GetComponent("particledestroyer").SendMessage("RemoveParticle", theParticle, SendMessageOptions.DontRequireReceiver);

HitPoints = HitPoints - 1;
}

I’m struggling to get the actual particle i’ve collided with in this second part… and in the first part I’m getting the error ‘RemoveAt’ is not a member of ‘(UnityEngine.Particle)’, I guess because ‘particles’ isn’t really an array?? Color me lost.

I guess RemoveAt doesn’t belong to the array’s functions; maybe push, pull or something else.
Let me take a look…

EDITED:--------------------------------
As i believed, RemoveAt belongs to ArrayList’s functions.

In Action Script you can use delete Array[index] to eliminate the stored value in index position.

Another thing you can do is make an auxiliary array where to copy all elements you want to keep, excluding -of course- the collided particle.

ok thanks.

So i now have:

var tempArr = new Array ();

function RemoveParticle (theParticle) {
print ("Removing Particle");
// extract the particles
var particles = particleEmitter.particles;

tempArr = particles;

for (var i=0; i<tempArr.length; i++) {

if (i==theParticle){
tempArr[i].RemoveAt(i);
}

}
// copy them back to the particle system
particles = tempArr;
particleEmitter.particles = particles;
}

to remove the particle (which looks like it’ll work, no errors now at least!), but I still can’t actually get the specific particle i’ve collided with. As above i’m currently using:

function OnParticleCollision(other : GameObject){
var theParticle = Particle;
other.GetComponent("particledestroyer").SendMessage("RemoveParticle", theParticle, SendMessageOptions.DontRequireReceiver);

HitPoints = HitPoints - 1;
}

but clearly the ‘theParticle’ bit isn’t right. Can anyone help me detect the individual particle i’ve hit?

EDIT: Actually forget this, even though i’m not getting the particle to disappear yet, it’s sending way too many messages (because i’m colliding with so many particles) that it’s slow as hell… Back the the drawing board.

Are your particles static (still) or in motion? If they’re still then you can build lookup tables and delete the particles extremely fast.

moving, unfortunately :slight_smile:

How many particles are we talking about here?

Carwash, the code that you attached to the particle emitter, is wrong.

In the corrected code, you create a temp array and wrote this:

var particles = particleEmitter.particles;

tempArr = particles;

for (var i=0; i<tempArr.length; i++) {

if (i==theParticle){
tempArr[i].RemoveAt(i);
}

particles is an array (because i understand java script recognise it as one), so the code above it is the same like folllowing:

var particles = particleEmitter.particles;

for (var i=0; i<tempArr.length; i++) {

if (i==theParticle){
particles [i].RemoveAt(i);
}

Which is too similar to what you did at first attemp. The problem is that in that case you omit [/b]:
var particles = particleEmitter.particles;
for (var i=0; i<particles.Length; i++) {
if (i==theParticle){
particles__[/b].RemoveAt(i);
}
Anyway, it won’t work either because, how i told you, “RemoveAt” doesn’t belong to an array but ArrayList (that is not the same).
You may do something like this:
```__

*function RemoveParticle (theParticle) {

var particles = particleEmitter.particles;
for (var i=0; i<particles.Length; i++) {

if (particles[i]==theParticle){
delete particles[i];
//or you can try this: particles[i] = null;
}

}
// copy them back to the particle system
particleEmitter.particles = particles;
}

__*__</em></strong> <strong><em>__*Okay, now let's go to OnParticleCollision().*__</em></strong> <strong><em>__**__

*function OnParticleCollision(other : GameObject){
//what?! where did you get Particle? how do you know Particle is the particle you want?
var theParticle = Particle;
other.GetComponent(“particledestroyer”).SendMessage(“RemoveParticle”, theParticle, SendMessageOptions.DontRequireReceiver);

HitPoints = HitPoints - 1;
}

__```*

So, now we only have THAT problem… we don’t know how to recover the particle which has collisioned.__

if you do not require a scripting solution, consider the following:

add a World Particle Collider component to your game object that has your Particle Emitter.

set the Min Kill Velocity to 99999.

all particles that collide and have a velocity less than or equal to 99999 will be removed from the world.

1 Like

loopyllama, works perfectly :slight_smile:

I made something simple, it’s not really effiecient yet. it’s in C#
(this is for rain, if the direction isn’t fixed then use spherecast)

using UnityEngine;
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;

public class rain : MonoBehaviour
{

    public List<Particle> particles = new List<Particle>();


    void Update()
    {
        particles = particleEmitter.particles.ToList();

        for (int i = 0; i < particles.Count; i++)
        {
            var p = particles[i];
            if (Physics.Raycast(p.position, -Vector3.up, 0.1f))
            {
                particles.Remove(p);

            }
        }
        particleEmitter.particles = particles.ToArray();
    }
}
void OnParticleCollision(GameObject other)
    {
        //Number of particles
        int numCollisionEvents = part.GetCollisionEvents(other, collisionEvents);

                //Make sure a particle exists first....
                if (part.GetParticles(particles) > 0)
                {
                    //Stop the particle from generating more than one so we move it to somewhere else so it wont collide
                    particles[numCollisionEvents - 1].position = Vector3.zero;
                    //Update the particle system with the new position
                    part.SetParticles(particles);
                }
            }

Performance worthy? I think unity miss these basic functionalities so people spend more time making plugins so they can figure it out when people upload their code worthy assets :slight_smile: