Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Extending Grappling Hook & Collision Detection
#4
Hello again!

Thank you so much for the advice. I figured there was a better way of doing this.

I tried your suggestion of using the raycast and that has improved things. I am still seeing some tunnelling but that is now a function of the extend speed. Basically the faster the tether extends the greater the distance from the last particle's position previous frame vs current frame..

For the benefit of the other folks out there, here is my code.

Code:
IEnumerator ExtendTetherCR()
{

    yield return null; //skip a step. then go.

    extending = true;
    extended = false;
    retracting = false;
    retracted = false;
    lastParticleCollided = false;
    lastParticleAttached = false;


    // Procedurally generate the rope path (just a short segment, as we will extend it over time):
    int filter = ObiUtils.MakeFilter(collidesWithMask, collisionCategory);
    blueprint.path.Clear();
    blueprint.path.AddControlPoint(Vector3.zero, Vector3.zero, Vector3.zero, Vector3.up, sectionMass, sectionRotMass, 0.1f, filter, Color.white, "Start");
    blueprint.path.AddControlPoint(localDirection * 0.1f, Vector3.zero, Vector3.zero, Vector3.up, sectionMass, sectionRotMass, 0.1f, filter, Color.white, "End");
    blueprint.path.FlushEvents();

    // Generate the particle representation of the rope (wait until it has finished):
    yield return blueprint.Generate();

    // Set the blueprint (this adds particles/constraints to the solver and starts simulating them).
    rope.ropeBlueprint = blueprint;
    rope.GetComponent<ObiRopeExtrudedRenderer>().enabled = true;

    yield return new WaitForFixedUpdate();
    yield return null;

    ObiParticleGroup startPG = rope.ropeBlueprint.groups[0];
    shipPA.target = shipAttachment.transform;
    shipPA.particleGroup = startPG;
    shipPA.attachmentType = ObiParticleAttachment.AttachmentType.Dynamic;

    cursor.cursorMu = 0.0f;  //cursorMu controls where new particles will be added to or removed from. curosorMu=0 means start of rope, cursorMu=1 means end of rope
    cursor.direction = true; //true means we extend from start to end.

    Vector3 direction = tetherDirectionHandle.transform.localPosition.normalized;

    Vector3 lastParticlePosOld = Vector3.zero;

    while (true)
    {

        Vector3 origin = solver.transform.InverseTransformPoint(rope.transform.position);

        float length = 0;

        if (!lastParticleCollided)
        {

            for (int i = 0; i < rope.elements.Count; ++i)
            {
                int p1 = rope.elements[i].particle1;
                int p2 = rope.elements[i].particle2;

                solver.prevPositions[p1] = solver.positions[p1] = origin + direction * length;
                length += rope.elements[i].restLength;
                solver.prevPositions[p2] = solver.positions[p2] = origin + direction * length;
            }

            //after positioning the particles in a line, we want to cast a ray from the last particle to see if we hit anything. if we do, we stop extending in a straight line and let the physics take over.
            int lastParticle = rope.elements[rope.elements.Count - 1].particle2;  //first step is to get the index for the last particle in the rope. this is the one we will cast from.
            Vector3 lastParticlePos = solver.transform.TransformPoint(solver.positions[lastParticle]); //then we get the world position for that particle from the solver.

            //if lastParticlePosOld is zero, it means this is the first step and we haven't positioned the particles yet, so we skip the raycast.
            if (lastParticlePosOld != Vector3.zero)
            {
                Vector3 rayDirection = lastParticlePos - lastParticlePosOld;

                RaycastHit2D hit = Physics2D.Raycast(lastParticlePosOld, rayDirection, rayDirection.magnitude, collisionMask); //cast the ray and see if it hits anything in the collision mask.

                if (hit.collider != null)
                {
                    //if we hit something, we stop extending in a straight line and let the physics take over
                    //Debug.Log("Hit something! Stopping straight extension. Hit point: " + hit.point);
                    lastParticleCollided = true;

                    if (((1 << hit.collider.gameObject.layer) & attachmentMask) != 0)
                    {
                        //Debug.Log("Hit something we can attach to!");
                                                                                
                        ObiParticleGroup endPG = rope.ropeBlueprint.groups[1];

                        otherPA = rope.gameObject.AddComponent<ObiParticleAttachment>();
                        otherPA.target = hit.collider.transform;
                        
                        otherPA.particleGroup = endPG;
                        otherPA.attachmentType = ObiParticleAttachment.AttachmentType.Dynamic;
                        lastParticleAttached = true;

                    }
                }
            }
                        
            lastParticlePosOld = lastParticlePos;  // record the last particle position for the next step..
        }

        float distanceLeft = tetherTargetLength - cursor.ChangeLength(tetherShootSpeed * Time.deltaTime);
        //Debug.Log("distanceLeft: " + distanceLeft);

        if (distanceLeft < 0)
        {
            cursor.ChangeLength(distanceLeft);
            break;
        }


        yield return null;


    }


    yield return new WaitForFixedUpdate();
    yield return null;

    extending = false;
    extended = true;
    retracting = false;
    retracted = false;


}
Reply


Messages In This Thread
RE: Extending Grappling Hook & Collision Detection - by docgonzzo - 14-05-2026, 02:08 AM