Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Counting total particles into bucket
#1
Hi,

Using the Obi Fluid faucet and bucket example but with a lifespan of say 5 on the particles, how would I go about counting the total particles that have entered the bucket?  This would include the particle count after the lifespan of the current particles expire and new particles are generated.  Basically what I'm trying to do is allow the user to move the bucket and calculate a score based on how many particles enter the bucket in total.  The liquid stream may come in bursts (e.g. 500 in 1 second, then the particles are expired and another round comes a few seconds later), or it may be a constant stream but just 500 active particles at any one time.

So if they catch all the particles in the first stream I want the score to be 500, then those particles expire, and if they catch all the particles in the second stream the score would be 1000.

I've used the collider example and tested if the collider is the bucket, which gives me a current total count in the bucket.  Because the ID of the particles are reused when the expire, I can't keep a list of all particle IDs that have collided with the bucket.

Is there some sort of OnExpire event I can hook in to?  This way I could check at expire time if the particle is colliding with the bucket and add 1 to the overall score.

Thanks.
Reply
#2
(09-10-2018, 03:29 AM)FamilyGamesTime Wrote: Hi,

Using the Obi Fluid faucet and bucket example but with a lifespan of say 5 on the particles, how would I go about counting the total particles that have entered the bucket?  This would include the particle count after the lifespan of the current particles expire and new particles are generated.  Basically what I'm trying to do is allow the user to move the bucket and calculate a score based on how many particles enter the bucket in total.  The liquid stream may come in bursts (e.g. 500 in 1 second, then the particles are expired and another round comes a few seconds later), or it may be a constant stream but just 500 active particles at any one time.

So if they catch all the particles in the first stream I want the score to be 500, then those particles expire, and if they catch all the particles in the second stream the score would be 1000.

I've used the collider example and tested if the collider is the bucket, which gives me a current total count in the bucket.  Because the ID of the particles are reused when the expire, I can't keep a list of all particle IDs that have collided with the bucket.

Is there some sort of OnExpire event I can hook in to?  This way I could check at expire time if the particle is colliding with the bucket and add 1 to the overall score.

Thanks.

Every frame, count the particles that are inside the bucket but weren't the last frame, or count those that are no longer there but were the previous frame.

You can easily do this by keeping a set of last frame particles, and using ExceptWith() to determine particle enter/exit events. Some sample code:

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

    ObiSolver solver;
    public int counter = 0;
    public Collider targetCollider = null;
    
    Obi.ObiSolver.ObiCollisionEventArgs frame;
    HashSet<int> particles = new HashSet<int>();

    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)
    {
        HashSet<int> currentParticles = new HashSet<int>();
        
        for(int i = 0;  i < e.contacts.Count; ++i)
        {
            if (e.contacts.Data[i].distance < 0.001f)
            {

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

                    if (collider == targetCollider)
                        currentParticles.Add(e.contacts.Data[i].particle);

                }
            }
        }

        particles.ExceptWith(currentParticles);
        counter += particles.Count;
        particles = currentParticles;
    }

}
Reply