Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Flickering - solvers effect each other
#1
Hi All,
First of all - I have to say that i really like this product, simulations are very realistic, fast, configurable - well done! (documentation could be improvedSonrisa

using unity 2018.2.1f1 
using Obi 4.0.2

My real scene is a little complex with many moving solvers/emitters, so I built a simple demo scene to demonstrate the problem.
In general: fluid stream collide with a sphere, collided particles are being killed, and for every killed particle a new particle is emitted from a local emitter on the sphere

The demo scene includes the following GameObjects/Components:
1)MainSolver - Empty with a solver (global space) and a script MainCollisionDetection(described bellow)
(solver constraints copied from Obi sample scene "FluidViscosity")
2)MainEmitter - Empty with an ObiEmitter (that uses MainSolver as its solver) and particle renderer
  emitter properties: speed: 5, emitter material: Honey, collision material :very sticky
3)Sphere - unity sphere with ObiCollider ,RB, and ObiRB
  a)SphereSolver - child of Sphere - Empty with a solver (local space)
    (solver constraints copied from Obi sample scene "FluidViscosity")
    1. SphereEmitter - child of SphereSolver - empty with an ObiEmitter (that uses SphereSolver as its solver) and particle renderer
       emitter properties: speed: controlled by script SphereEmitionControl (described bellow), emitter material: Honey, collision material :very sticky 

4)MainCollisionDetection script detects collisions (on MainSolver), kills the hitting particle, and adds the particle collision data to a queue in the SphereEmitionControl script
Code:
using System.Collections.Generic;
using UnityEngine;
using Obi;

public class MainCollisionDetection : MonoBehaviour {

   public ObiEmitter mainEmitter;
   ObiSolver solver;

   Obi.ObiSolver.ObiCollisionEventArgs frame;
   List<int> allreadyEmittedParticles;

   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)
   {
       frame = e;
       if (solver == null || frame == null || frame.contacts == null) return;

       allreadyEmittedParticles = new List<int>();
       int closeContacts = 0;

       for (int i = 0; i < frame.contacts.Count; ++i)
       {
           
           if (frame.contacts[i].distance < 0.001f)
           {
               Component contactColl;
               ObiCollider.idToCollider.TryGetValue(frame.contacts[i].other, out contactColl);

               if (contactColl != null)
               {
                   ObiSolver.ParticleInActor pa = solver.particleToActor[frame.contacts[i].particle];
                   ObiEmitter emtr = pa.actor as ObiEmitter;
                   int particleIndexInEmitter = pa.indexInActor;

                   if (!allreadyEmittedParticles.Contains(particleIndexInEmitter))
                   {
                       allreadyEmittedParticles.Add(particleIndexInEmitter);
                       closeContacts++;

                       Vector3 point = frame.contacts[i].point;
                       Vector3 normal = frame.contacts[i].normal;

                       //kill hit particle in the main emitter
                       emtr.life[particleIndexInEmitter] = 0;

                       //look for the hitted collider emitter
                       ObiEmitter colliderEmitter = contactColl.GetComponentInChildren<ObiEmitter>();
                       
                       if (colliderEmitter != null)
                       {
                           SphereEmitionControl sphereEmitionControl = colliderEmitter.GetComponent<SphereEmitionControl>();

                           //add particle to collider emitter queue
                           sphereEmitionControl.AddParticleToEmit(point, Quaternion.Euler(normal));
                       }
                   }
               }  
           }
       }
   }
}

5)SphereEmitionControl script has a queue of particles positions/normals, it is filled only by data from MainCollisionDetection script.  The script repeatedly checks if the queue is not empty, it dequeues the data, move its transform to the stored position/normal and emit for a short while (i didn't know how to emit one particle so i timed the emittion with a coroutine)
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Obi;


public class ParticleToEmit
{
   public Vector3 pos;
   public Quaternion localRot;
}

public class SphereEmitionControl : MonoBehaviour {

   ObiEmitter m_emitter;
   bool emitting;
   Queue<ParticleToEmit> particlesToEmit;

   void Start()
   {
       m_emitter = GetComponent<ObiEmitter>();
       m_emitter.speed = 0f;
       particlesToEmit = new Queue<ParticleToEmit>();
   }

   void LateUpdate()
   {
       if (particlesToEmit.Count > 0 && !emitting)
       {
           ParticleToEmit par = particlesToEmit.Dequeue();
           transform.position = par.pos;
           transform.localRotation = par.localRot;
           StartCoroutine(ColliderEmitterEmit());
       }
   }

   //add a particle data to queue
   public void AddParticleToEmit(Vector3 pos, Quaternion localRot)
   {
       ParticleToEmit newParticle = new ParticleToEmit();
       newParticle.pos = pos;
       newParticle.localRot = localRot;
       particlesToEmit.Enqueue(newParticle);
   }

   //emit particle
   public IEnumerator ColliderEmitterEmit()
   {
       emitting = true;
       
       m_emitter.speed = 1f;
       m_emitter.EmitParticle(0);

       yield return null;
       
       m_emitter.speed = 0f;

       emitting = false;
   }
}


Regarding the collisions the scripts run OK , the problem is : the particles (emitted from SphereEmitter) are flickering.
I did some testing and found that:
case a: while running - if i disable the MainSolver (in the editor) the flickering stops (strange, it should not effect the scene because the particles belong to the SphereSolver)
case b: while running - if the MainSolver is enabled, and i disable and than enable the SphereSolver - flickering stops, and everything works well as expected, but now if i disable and than enable the MainSolver, flickering starts again

why does the flickering happen?
how to prevent it?

thanks,
shayk
Reply


Messages In This Thread
Flickering - solvers effect each other - by shayk - 09-03-2019, 11:11 AM