(20-05-2024, 09:29 AM)Harshid123 Wrote: Code:
public IEnumerator CheckIfTangled()
{
yield return new WaitForSeconds(1);
int filter = ObiUtils.MakeFilter(ObiUtils.CollideWithEverything, 1);
for (int i = 0; i < rope.activeParticleCount; ++i)
{
yield return null;
Vector3 pos = rope.GetParticlePosition(rope.solverIndices[i]);
Ray ray = new Ray(pos, Vector3.back * 10f);
if (solver.Raycast(ray, out QueryResult result, filter, 100, 0.5f))
{
int simplexStart = solver.simplexCounts.GetSimplexStartAndSize(result.simplexIndex, out int simplexSize);
for (int j = 0; j < simplexSize; ++j)
{
yield return null;
int particleIndex = solver.simplices[simplexStart + j];
ObiSolver.ParticleInActor pa = solver.particleToActor[particleIndex];
if (pa.actor != rope)
{
// rope is tangled here return.
yield break;
}
}
}
}
// rope is not tangled here.
}
I am pretty sure there could be other better workaround for this, But This code worked for me
This will only work in specific circumstances, since your ray has a fixed direction (Vector3.back). If the rope is colliding against another rope in a direction other than the one specified by your ray, this won't work. Moreover, casting a ray from every particle in your rope is a very brute force approach to this.
A simpler, faster, and more robust way is to use collision callbacks. You can simply count the amount of contacts affecting each rope, and determine whether a rope is colliding (contact count > 0) or not (contact count == 0).
Note you should not do this for every rope in your solver either, it's enough to iterate trough all contacts just once since they already contain references to the ropes involved in them. The typical approach would be to add a component to your ObiSolver, subscribe it to OnParticleCollision, and then count the contacts for each rope only once per frame - as opposed to subscribing every rope to OnParticleCollision and iterating trough all contacts in the solver as many times as ropes you have, which would also be very inefficient.
kind regards,