Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Destroy Individual Particle?

Discussion in 'Scripting' started by Carwash, Aug 9, 2010.

  1. Carwash

    Carwash

    Joined:
    Nov 12, 2009
    Posts:
    95
    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 :))

    Code (csharp):
    1. function OnParticleCollision(other : Particle){
    2. Destroy (other)
    3. }
     
  2. Kokumo

    Kokumo

    Joined:
    Jul 23, 2010
    Posts:
    416
  3. Carwash

    Carwash

    Joined:
    Nov 12, 2009
    Posts:
    95
    Thanks, good find. I guess i can go through the array and find the one i've collided with... wish me luck :)

    Something like this maybe? Any pointers appreciated.

    attached to Particle Emitter:
    Code (csharp):
    1. function RemoveParticle (theParticle) {
    2. print ("Removing Particle");
    3. // extract the particles
    4. var particles = particleEmitter.particles;
    5. for (var i=0; i<particles.Length; i++) {
    6.  
    7. if (i==theParticle){
    8. particles.RemoveAt(i);
    9. }
    10.  
    11. }
    12. // copy them back to the particle system
    13. particleEmitter.particles = particles;
    14. }

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


    Code (csharp):
    1. function OnParticleCollision(other : GameObject){
    2. var theParticle = Particle;
    3. other.GetComponent("particledestroyer").SendMessage("RemoveParticle", theParticle, SendMessageOptions.DontRequireReceiver);
    4.  
    5. HitPoints = HitPoints - 1;
    6. }
    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.
     
  4. Kokumo

    Kokumo

    Joined:
    Jul 23, 2010
    Posts:
    416
    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.
     
  5. Carwash

    Carwash

    Joined:
    Nov 12, 2009
    Posts:
    95
    ok thanks.

    So i now have:
    Code (csharp):
    1. var tempArr = new Array ();
    2.  
    3. function RemoveParticle (theParticle) {
    4. print ("Removing Particle");
    5. // extract the particles
    6. var particles = particleEmitter.particles;
    7.  
    8. tempArr = particles;
    9.  
    10. for (var i=0; i<tempArr.length; i++) {
    11.  
    12. if (i==theParticle){
    13. tempArr[i].RemoveAt(i);
    14. }
    15.  
    16. }
    17. // copy them back to the particle system
    18. particles = tempArr;
    19. particleEmitter.particles = particles;
    20. }
    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:

    Code (csharp):
    1. function OnParticleCollision(other : GameObject){
    2. var theParticle = Particle;
    3. other.GetComponent("particledestroyer").SendMessage("RemoveParticle", theParticle, SendMessageOptions.DontRequireReceiver);
    4.  
    5. HitPoints = HitPoints - 1;
    6. }
    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.
     
  6. Chris-Sinclair

    Chris-Sinclair

    Joined:
    Jun 14, 2010
    Posts:
    1,326
    Are your particles static (still) or in motion? If they're still then you can build lookup tables and delete the particles extremely fast.
     
  7. Carwash

    Carwash

    Joined:
    Nov 12, 2009
    Posts:
    95
    moving, unfortunately :)
     
  8. Chris-Sinclair

    Chris-Sinclair

    Joined:
    Jun 14, 2010
    Posts:
    1,326
    How many particles are we talking about here?
     
  9. Kokumo

    Kokumo

    Joined:
    Jul 23, 2010
    Posts:
    416
    Carwash, the code that you attached to the particle emitter, is wrong.

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

    Code (csharp):
    1.  
    2. var particles = particleEmitter.particles;
    3.  
    4. tempArr = particles;
    5.  
    6. for (var i=0; i<tempArr.length; i++) {
    7.  
    8. if (i==theParticle){
    9. tempArr[i].RemoveAt(i);
    10. }
    11.  
    12.  
    particles is an array (because i understand java script recognise it as one), so the code above it is the same like folllowing:

    Code (csharp):
    1.  
    2. var particles = particleEmitter.particles;
    3.  
    4. for (var i=0; i<tempArr.length; i++) {
    5.  
    6. if (i==theParticle){
    7. particles [i].RemoveAt(i);
    8. }
    9.  
    10.  
    Which is too similar to what you did at first attemp. The problem is that in that case you omit :
    var particles = particleEmitter.particles;

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

    if (i==theParticle){
    particles.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:

    Code (csharp):
    1.  
    2. function RemoveParticle (theParticle) {
    3.  
    4. var particles = particleEmitter.particles;
    5. for (var i=0; i<particles.Length; i++) {
    6.  
    7.  
    8. if (particles[i]==theParticle){
    9. delete particles[i];
    10. //or you can try this: particles[i] = null;
    11. }
    12.  
    13. }
    14. // copy them back to the particle system
    15. particleEmitter.particles = particles;
    16. }
    17.  
    Okay, now let's go to OnParticleCollision().

    Code (csharp):
    1.  
    2. function OnParticleCollision(other : GameObject){
    3. //what?! where did you get Particle? how do you know Particle is the particle you want?
    4. var theParticle = Particle;
    5. other.GetComponent("particledestroyer").SendMessage("RemoveParticle", theParticle, SendMessageOptions.DontRequireReceiver);
    6.  
    7. HitPoints = HitPoints - 1;
    8. }
    9.  
    So, now we only have THAT problem... we don't know how to recover the particle which has collisioned.
     
  10. loopyllama

    loopyllama

    Joined:
    Apr 6, 2009
    Posts:
    71
    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.
     
    Kerihobo likes this.
  11. Arunraj

    Arunraj

    Joined:
    Jul 4, 2012
    Posts:
    21
    loopyllama, works perfectly :)
     
  12. 1elfdragon1

    1elfdragon1

    Joined:
    Apr 13, 2012
    Posts:
    3
    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)

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System;
    4. using System.Linq;
    5. using System.Collections;
    6. using System.Collections.Generic;
    7.  
    8. public class rain : MonoBehaviour
    9. {
    10.  
    11.     public List<Particle> particles = new List<Particle>();
    12.  
    13.  
    14.     void Update()
    15.     {
    16.         particles = particleEmitter.particles.ToList();
    17.  
    18.         for (int i = 0; i < particles.Count; i++)
    19.         {
    20.             var p = particles[i];
    21.             if (Physics.Raycast(p.position, -Vector3.up, 0.1f))
    22.             {
    23.                 particles.Remove(p);
    24.  
    25.             }
    26.         }
    27.         particleEmitter.particles = particles.ToArray();
    28.     }
    29. }
    30.  
    31.  
     
    Last edited: Feb 18, 2014
  13. Enumerator_T

    Enumerator_T

    Joined:
    Nov 5, 2014
    Posts:
    16
    Code (CSharp):
    1. void OnParticleCollision(GameObject other)
    2.     {
    3.         //Number of particles
    4.         int numCollisionEvents = part.GetCollisionEvents(other, collisionEvents);
    5.  
    6.                 //Make sure a particle exists first....
    7.                 if (part.GetParticles(particles) > 0)
    8.                 {
    9.                     //Stop the particle from generating more than one so we move it to somewhere else so it wont collide
    10.                     particles[numCollisionEvents - 1].position = Vector3.zero;
    11.                     //Update the particle system with the new position
    12.                     part.SetParticles(particles);
    13.                 }
    14.             }
    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 :)