Yesterday, 11:41 AM
(Yesterday, 11:31 AM)josemendez Wrote: Not going to happen, since per-actor callbacks have the exact same problems as per-particle callbacks: it's impossible to do in the GPU (you cannot call back to the CPU from the GPU mid-dispatch), executed in worker threads in the CPU.Thanks for explaination. I'll try this to see whether it works.
Obi provides a single callback for all contacts at the end of each simulation step. This is efficient, always doable, and always happens in the main thread. It also provides the same data used by the engine internally (same system used by force zones), so it comes at a very small cost compared to per-particle or per-actor callbacks.
You can do this using the existing collision callback. It's easy to retrieve the actor/force zone per contact and apply your custom force/acceleration/etc.
Here's a slightly modified version of the sample code found in the manual. It finds all particles inside a specific trigger and applies a custom acceleration to them, depending on which actor they belong to.
Code:[RequireComponent(typeof(ObiSolver))]
public class ZeroGravityZone: MonoBehaviour
{
ObiSolver solver;
void Awake()
{
solver = GetComponent<ObiSolver>();
}
void OnEnable()
{
solver.OnCollision += Solver_OnCollision;
}
void OnDisable()
{
solver.OnCollision -= Solver_OnCollision;
}
void Solver_OnCollision(object sender, ObiNativeContactList e)
{
var world = ObiColliderWorld.GetInstance();
foreach (Oni.Contact contact in e)
{
// this one is an actual collision:
if (contact.distance < 0.01)
{
ObiColliderBase col = world.colliderHandles[contact.bodyB].owner;
// if this is a force zone:
if (col != null && col.TryGetComponent(out ObiForceZone zone))
{
// get the index of the particle inside the force zone:
int particleIndex = solver.simplices[contact.bodyA];
// get the actor it belongs to:
ObiActor actor = solver.particleToActor[particleIndex].actor;
// apply different acceleration depending on the actor.
if (actor == myActor)
solver.velocities[particleIndex] += contact.normal * zone.intensity * Time.deltaTime;
else
solver.velocities[particleIndex] -= contact.normal * zone.intensity * Time.deltaTime;
}
}
}
}
}