Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Oncollision detection and cut rope problem
#2
(17-11-2021, 05:36 PM)greyhawk Wrote: Greetings, I am working with OnCollision on a  mechanic that will cut the  rope as a result of contact with objects such as saws, knives and similar objects that can cut the rope.

In addition,3 ropes can interact physically with each other. Trying to cut one, the other is cut. Each one has its own blueprint.

How can I fix the bug in the code I wrote?

You can see the script I wrote
Code:
using System.Collections.Generic;
using UnityEngine;
using Obi;

namespace _Game.Scripts.Entities.Rope
{
    [RequireComponent(typeof(ObiSolver))]
    public class RopeCutter : MonoBehaviour
    {
        ObiSolver solver;
        public List<ObiStructuralElement> ropeElements;
       
        void Awake(){
            solver = GetComponent<Obi.ObiSolver>();
        }

        void OnEnable () {
            solver.OnCollision += Solver_OnCollision;
        }

        void OnDisable(){
            solver.OnCollision -= Solver_OnCollision;
        }
        void Solver_OnCollision(object sender, ObiSolver.ObiCollisionEventArgs e)
        {
            var world = ObiColliderWorld.GetInstance();

            // just iterate over all contacts in the current frame:
            foreach (Oni.Contact contact in e.contacts)
            {
                // if this one is an actual collision:
                if (contact.distance < 0.01);
                {
                    ObiColliderBase col = world.colliderHandles[contact.bodyB].owner;
                    if(col !=null)
                    TearRope(col, contact);
                }
               
            }
        }

        private void TearRope(ObiColliderBase col, Oni.Contact contact)
        {
            if (!col || !col.CompareTag("saw")) return;
            //int particleIndex = solver.simplices[contact.bodyA];
            ObiSolver.ParticleInActor pa = solver.particleToActor[contact.bodyA];
            if (pa == null) return;

            var actor = pa.actor as ObiRope;
            if (!actor) return;
      
            if (pa.indexInActor >= actor.elements.Count) return;

            actor.Tear(actor.elements[pa.indexInActor]);
            actor.RebuildConstraintsFromElements();
        }
       
    }
}

Hi!

You're using contact.bodyA as the particle index (which it isn't), should be:

Code:
int particleIndex = solver.simplices[contact.bodyA];

then use particleIndex to access solver arrays.

Also, you're using the actor particle index (pa.indexInActor) to access the elements array, which does not make sense and may result in out of bounds access errors - this is why I think you're checking if the index is larger the elements array, which should not be necessary. Elements and particles are different things. To find the element that contains the particle you want, iterate trough the elements. Your TearRope code should look like this:

Code:
private void TearRope(ObiColliderBase col, Oni.Contact contact)
{

// get the particle index:
int particleIndex = solver.simplices[contact.bodyA];

// retrieve the actor this particle belongs to:
ObiSolver.ParticleInActor pa = solver.particleToActor[particleIndex];
var actor = pa.actor as ObiRope;

// not a rope, stop:
if (actor == null) return;

// check rope elements and tear the one that references this particle:
foreach (var elm in actor.elements)
{
   if (elm.particle1 == particleIndex)
   {
      actor.Tear(elm);
      actor.RebuildConstraintsFromElements();
      break;
   }
}

}
Reply


Messages In This Thread
RE: Oncollision detection and cut rope problem - by josemendez - 18-11-2021, 09:06 AM