Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Extending Grappling Hook & Collision Detection
#6
Thanks so much for all the help it is much appreciated. Excellent support here for this asset, as always.

It took some time, but I think I understand what you were suggesting. I implemented it and it seems to be working well.

On the final element of the rope, before moving that last particle, I do the raycast check and if it hits something I reset length.

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;

        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;
        
        while (true)
        {
            Vector3 origin = solver.transform.InverseTransformPoint(rope.transform.position);

            float length = 0;

            if (!lastParticleCollided)
            {
                //extend the rope in a straight line by moving the positions of the active particles.
                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;

                    if(i == rope.elements.Count - 1)
                    {///before we place the last particle of the last element, check if there is anything in that path using a raycast.

                        Vector3 rayStart = solver.transform.TransformPoint(solver.positions[p2]);
                        Vector3 rayEnd = solver.transform.TransformPoint(origin + direction * length);
                        Vector3 rayDirection = rayEnd - rayStart;

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

                        if (hit.collider != null)
                        {
                            //Debug.Log("Hit something! hit.collider.name: " + hit.collider.name);
                            lastParticleCollided = true;

                            //length needs to be reset to be the distance from the rope's origin to the point the raycast hit something.
                            length = ( (Vector3)hit.point - rope.transform.position ).magnitude;

                            if (((1 << hit.collider.gameObject.layer) & attachmentMask) != 0)
                            {
                                //Debug.Log("Hit something we can attach to!");
                                lastParticleAttached = true;
                                //add a particle attachment, and set it's target to be the collider we hit in the raycast.
                                otherPA = rope.gameObject.AddComponent<ObiParticleAttachment>();
                                otherPA.target = hit.collider.transform;
                            }
                        }
                    }
                    //move the last particle of the rope into position (before attaching it, if applicable).
                    solver.prevPositions[p2] = solver.positions[p2] = origin + direction * length;

                    if(lastParticleAttached)
                    {
                        ObiParticleGroup endPG = rope.ropeBlueprint.groups[1];
                        otherPA.particleGroup = endPG;
                        otherPA.attachmentType = ObiParticleAttachment.AttachmentType.Dynamic;

                    }
                        


                        

                }
                                

                
            }

            float distanceLeft = tetherTargetLength - cursor.ChangeLength(tetherShootSpeed * Time.deltaTime);

            


            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 - 15-05-2026, 03:03 AM