Most of the time, you will want your particles to be able to collide with and react to other elements in your scene: walls, floor, crates, and whatnot. They can also collide with each other! These two types of collisions (against colliders and against other particles) can be controlled independently in Obi. Everything in this section applies to all Obi actors (cloth, ropes, fluid emitters, etc) so it's a quite important topic.
Enabling collision constraints in the ObiSolver component allows particles to collide against ObiColliders.
Add an ObiCollider component to any collider in your scene to make it work with Obi particles. You can add this component to SphereColliders, MeshColliders, BoxColliders... pretty much all standard Unity colliders, both 3D and 2D. The only collider types not currently supported by Obi are PolygonCollider2D and TilemapCollider2D. At the beginning of each simulation step, solvers will generate collision constraints for all their particles based on what colliders are spatially close to them.
This is how the ObiCollider component inspector looks like:
Sometimes you need a collider to be ignored by specific actors - or even specific particles: you can use categories and masks for this.
Each collider/particle can be in one of up to 16 collision categories, from 0 to 15. The "Collides with" mask determine which categories a collider or particle is allowed to collide with. It's possible for a mask to allow collisions with more than one category, or with all of them.
For instance: a particle in category 5 with a mask that allows collision with categories 8 and 10 would collide against any particle or collider in categories 8 and 10 whose mask also allows collisions with category 5.
By default colliders and particles are set in category 0, and their mask allows collisions with all categories.
if ((A.mask & B.category != 0) && (B.mask & A.category) != 0) MayCollide(A,B);
In the following animation the floor colliders are set to collide only with categories 0, 1 and 2, from top to bottom. The cloth balloons are set in categories 0, 1 and 2, from left to right.
All ObiActors allow you to set categories and masks for individual particles. Depending on the actor, this is done in slightly different ways:
Positive thickness values will leave a gap between the collider surface and colliding particles. Negative values will cause particles to "sink" into the collider before actually hitting its surface.
Turns the collider inside out, so particles collide with the inwards side of the collider's surface.
ObiColliders also allow you to set their collision material . This determines how actors react when colliding against them: whether they slip or stop due to friction, or whether they stick to it or not.
This is the Collider that the ObiCollider is exposing to solvers. When you add a ObiCollider component to an object, this field will automatically be populated with the first Collider component found in the object. In cases where you have multiple Collider components in a single object and you want them all to be used by Obi, you must add a ObiCollider for each Collider and manually assign the Source Collider property of each one.
Distance fields (widely known as SDFs) are a special data structure that precomputes and stores distances to the surface of a collider. This gets rid of the need to calculate the distance between particles and the collider analytically during the simulation, making them well suited for efficient and robust collision detection against complex colliders. If you're dealing with a moving and/or complex MeshCollider, consider creating a distance field and assigning it to this property.
When you add an ObiCollider component to an object, it will look for the first Rigidbody component up its hierarchy and attach an ObiRigidbody component to it. This allows for full two-way coupled interaction between Obi particles and rigidbodies. If you delete this component, Obi will recreate it automatically the next time you hit "Play".
ObiRigidbody only has one parameter: "Kinematic for particles". Enabling this shields the rigidbody from any forces applied by particles, so it will behave as if no Obi particles were present in the scene. The particles will still "feel" the rigidbody and collide with it, though.
Enabling particle collision constraints in an ObiSolver component allows particles in the solver to collide with each other. We make a distinction between two kinds of particle collision, depending on which actor the particles involved in the collision belong to: if the particles belong to different actors, it's an inter-collision. If they belong to the same actor, it's a self-collision.
Provided that the solver has particle collision constraints enabled, ObiActors simulated by that solver will collide with each other. Keep in mind that particles simulated by different solvers cannot interact with each other, which means actors in different solvers won´t be able to collide with each other.
Assuming your solver has particle collision constraints enabled, you can allow an actor to collide with itself by enabling the "self-collisions" checkbox in its inspector.
Obi 6.0 and up allows you to use surface-based collision detection on a per-actor basis, which is more accurate than particle-based. To use it, all you need to do is enable the "surface collisions" checbox in your actor's inspector. For details, see surface collisions.
Obi's collision pipeline is split into 3 steps: the broadphase, where objects (colliders, simplices or particles) are tested for rough spatial proximity. The narrowphase, where potentially colliding pairs generated by the broadphase are filtered, processed and contacts are generated. And finally, collision projection, where the trajectories of simplices/particles/rigidbodies involved in each contact are adjusted to prevent collision.
You can adjust various parameters of the collision pipeline in the solver settings. These will affect how the bounding boxes for particles and colliders are built, and how contacts are generated.
Once you´ve set up collisions, your solver will begin generating collision constraints (aka contacts) for particles, using the 3 steps outlined above. Obi uses a collision detection paradigm known as "speculative contacts". This means contacts will be generated before any actual collision has taken place between particles, or between colliders and particles. Thanks to this, the trajectory of particles in collision course are corrected before the collision actually takes place, and tunneling issues (the well known bullet-trough-paper problem existing in most collision engines) are almost non-existant. Contacts are detected and resolved even at high speeds. Also, TOI (time of impact) ordering is not needed if several collisions happen in the same frame.
Some contacts never cease to be "speculative", they do not progress past the broadphase and they're never actually resolved. Some others eventually progress to a real collision, and collision resolution takes place.
Several contacts can be generated for a given particle in the same frame. Then, speculative contacts must be accounted for and then resolved if they turn out to be actual collisions. However, resolving contacts sequentially (one after another) can unfortunately cause previously resolved contacts to become collisions again. See the following diagram: In step 1, two speculative contacts are generated because according to the orange particle's current velocity, it is almost certain it will collide with the grey collider in the next frame. In step 2, both speculative contacts progress to actual collisions that must be resolved. Step 3 shows how the right collision is resolved first. In step 4 we resolve the left one, but this causes penetration for the right one again. We must solve the right collision a second time (step 5) to ensure no penetration happens for either contact.
All this right, left, right, left... iterative solving causes visual jittering, as we see the particle jump between two configurations until all collisions are resolved (which can take a very high amount of iterations). For this reason, Obi lets you decide (as it does with all constraint groups) how collisions must be resolved: sequentially or in parallel. In parallel mode, all contacts are resolved independently in the same step (as if the others did not exist) and the final correction is calculated as an average of all their individual results. This increases stablity (removing jittering due to unresolved collisions) but decreases convergence speed (achieving zero-penetration takes more iterations) making collisions seem too "soft" when using low iteration counts. See the next diagram:
General rule of thumb: If multiple collisions can happen at once in your scene and jittering is an issue, set your collision constraints evaluation order to "parallel". If jittering is not a problem and/or you need faster convergence, use "sequential" evaluation order. There are separate controls for particle-particle collisions and particle-collider collisions, so you can use different methods for each of them. You can find this settings in the ObiSolver inspector, under "Particle Collision Constraint Parameters" and "Collision Constraint Parameters":
See ObiSolver for more info on sequential vs parallel solving.
Shock propagation is a technique that modifies particle masses internally during contact resolution, so that particles at the bottom of a pile have higher effective mass that the ones at the top. This results in faster convergence and stabler stacking. You can find this parameter in the ObiSolver inspector, it is applied globally per-solver. Use this when you need an extra "oomph" for your particle-particle contacts, specially when creating piles of granular material.