Obi Official Forum
Help Destroy particle on collision - Printable Version

+- Obi Official Forum (https://obi.virtualmethodstudio.com/forum)
+-- Forum: Obi Users Category (https://obi.virtualmethodstudio.com/forum/forum-1.html)
+--- Forum: Obi Fluid (https://obi.virtualmethodstudio.com/forum/forum-3.html)
+--- Thread: Help Destroy particle on collision (/thread-161.html)

Pages: 1 2


Destroy particle on collision - Kalidor - 29-09-2017

Hi!

It's me again Guiño.

I want to kill a particle on collision.
How can i handle that?


RE: Destroy particle on collision - josemendez - 29-09-2017

(29-09-2017, 10:50 AM)Kalidor Wrote: Hi!

It's me again Guiño.

I want to kill a particle on collision.
How can i handle that?
There is a KillParticle method in the emitter, but i'am trying to get the correct index of the particle.

Hi!

You can retrieve it like this:

Code:
solver.particleToActor[contact.particle].indexInActor

contact.particle is the particle index in the entire solver. Since a single solver can manage multiple emitters (i.e. actors) and generally index in solver != index in actor, you can use the particleToActor array to know the particle index in its emitter.

Then you can use KillParticle to kill it.


RE: Destroy particle on collision - Kalidor - 29-09-2017

Thank you for the support!

Mmh, i'am trying to kill all particles in the collision loop.
At the beginning it works. Later the wrong particles get killed. 
(maybe second time new created particles cause the problem) 


RE: Destroy particle on collision - josemendez - 29-09-2017

(29-09-2017, 12:30 PM)Kalidor Wrote: Thank you for the support!

Mmh, i'am trying to kill all particles in the collision loop.
At the beginning it works. Later the wrong particles get killed. 
(maybe second time new created particles cause the problem) 

Yes! you're 100% right, my apologies. Since dead particles are swapped with the last living particle for better cache locality, this will cause successive calls to KillParticle() to fail if they're done in the wrong order.

The solution to this is to set the particle's life to zero, instead of calling KillParticle() (in fact, I will make this method private in the future to avoid other users -and myself- to fall in this trap again). This will ensure the emitter itself kills the correct particles as soon as the next frame starts.

Code:
emitter.life[solver.particleToActor[contact.particle].indexInActor] = 0;

In addition to this, there was a bug in the emitter in version 3.2, emitters did not update the particleToActor array correctly when spawning new particles. Attached you'll find an updated ObiEmitter.cs script, you must replace yours with this one.

Thanks a lot for pointing out this issue!


RE: Destroy particle on collision - Kalidor - 29-09-2017

There is the same problem with this solution (with your new script).


RE: Destroy particle on collision - josemendez - 29-09-2017

(29-09-2017, 02:45 PM)Kalidor Wrote: There is the same problem with this solution (with your new script).

Hi Kalidor,

I tested it with this code in a variety of situations, works as intended. Make sure that you set the particle's life to 0 instead of calling KillParticle().

Code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Obi;

[RequireComponent(typeof(ObiSolver))]
public class CollisionEventHandler : MonoBehaviour {

    ObiSolver solver;

   public Collider killer;

    void Awake(){
        solver = GetComponent<Obi.ObiSolver>();
    }

    void OnEnable () {
        solver.OnCollision += Solver_OnCollision;
    }

    void OnDisable(){
        solver.OnCollision -= Solver_OnCollision;
    }
    
    void Solver_OnCollision (object sender, Obi.ObiSolver.ObiCollisionEventArgs e)
    {
        for(int i = 0;  i < e.contacts.Length; ++i)
       {
           if (e.contacts[i].distance < 0.001f)
           {

               Component collider;
               if (ObiCollider.idToCollider.TryGetValue(e.contacts[i].other,out collider)){

                   if (collider == killer){

                       ObiSolver.ParticleInActor pa = solver.particleToActor[e.contacts[i].particle];
                       ObiEmitter emitter = pa.actor as ObiEmitter;

                       if (emitter != null)
                           emitter.life[pa.indexInActor] = 0;
                       
                   }
               }
           }
       }
   }
}



RE: Destroy particle on collision - Kalidor - 29-09-2017

That's strange... My source code looks equal.

I will check it these days.


RE: Destroy particle on collision - Kalidor - 02-10-2017

OK, now it works!
I had to replace your script again.
No idea why Unity didn't notice the first replacement...


RE: Destroy particle on collision - Jaydena - 03-05-2018

Hey Josemendez,

This script works well but it gets very inefficient after around 1000 particles have been emitted, dropping down to 4fps. 

Is there anyway to achieve this effect in a more efficient manner?

Such as set the particle life to zero based on it's z, x or y transform value rather than a collision?

Cheers!


RE: Destroy particle on collision - josemendez - 03-05-2018

(03-05-2018, 07:28 AM)Jaydena Wrote: Hey Josemendez,

This script works well but it gets very inefficient after around 1000 particles have been emitted, dropping down to 4fps. 

Is there anyway to achieve this effect in a more efficient manner?

Such as set the particle life to zero based on it's z, x or y transform value rather than a collision?

Cheers!

You could deactivate collisions and just iterate over all particles positions instead, yes.

Out of curiosity, I've tested this script and it only causes a 10% performance impact or so for 2500 particles. What platform are you targeting? and have you profiled to make sure this is the culprit?