Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
2D version of grappling hook demo
#1
I just bought this asset and the grappling hook demo provided seems like a good starting point for me. However my project is 2D so I'm using Rigidbody2Ds, ObiCollider2Ds, and so on.

After some wrangling I got to a point where I can spawn a rope just like in the demo. However the "2D" rope has a number of issues. It often causes my player to oscillate rapidly (which I fixed by increasing angular drag a lot, obviously not a great solution), the rope sometimes curls into the z axis for no clear reason (it's not running out of space or anything) despite absolutely none of the vectors I'm using having any z component. Often the resulting rope is just significantly longer than expected.

I more or less just copied the code from the grappling hook demo for my "attach hook method":


Code:
private void Awake()
{
    m_rope = gameObject.AddComponent<ObiRope>();

    // Create both the rope and the solver:    
    m_ropeRenderer = gameObject.AddComponent<ObiRopeLineRenderer>();
    //m_ropeRenderer.section = m_section;
    m_ropeRenderer.uvScale = new Vector2(1, 5);
    m_ropeRenderer.normalizeV = false;
    m_ropeRenderer.uvAnchor = 1;

    m_rope.GetComponent<MeshRenderer>().material = m_material;
    m_rope.maxBending = 0.02f;

    m_ropeBlueprint = ScriptableObject.CreateInstance<ObiRopeBlueprint>();
    m_ropeBlueprint.resolution = 0.5f;
       
    ...
}

private IEnumerator AttachHook(Vector3 worldSpacePoint, Collider2D hitCollider)
{
    yield return 0;
    Vector3 localHit = m_rope.transform.InverseTransformPoint(worldSpacePoint);
            
    // Procedurally generate the rope path (a simple straight line):
    m_ropeBlueprint.path.Clear();
    m_ropeBlueprint.path.AddControlPoint(Vector3.zero, -localHit.normalized, localHit.normalized, Vector3.up, 0.1f, 0.1f, 1, 1, Color.white, "Hook start");
    m_ropeBlueprint.path.AddControlPoint(localHit, -localHit.normalized, localHit.normalized, Vector3.up, 0.1f, 0.1f, 1, 1, Color.white, "Hook end");
    m_ropeBlueprint.path.FlushEvents();

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

    Debug.Break();

    // Pin both ends of the rope (this enables two-way interaction between character and rope):
    var pinConstraints = m_ropeBlueprint.GetConstraintsByType(Oni.ConstraintType.Pin) as ObiConstraints<ObiPinConstraintsBatch>;
    var batch = pinConstraints.batches[0];
    batch.AddConstraint(0, m_characterCollider, transform.localPosition, Quaternion.identity);
    batch.AddConstraint(m_ropeBlueprint.activeParticleCount - 1, hitCollider.GetComponent<ObiColliderBase>(),
                                                        hitCollider.transform.InverseTransformPoint(worldSpacePoint), Quaternion.identity);
    batch.activeConstraintCount = 2;

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

Note the addition of a Debug.Break() so I can examine the ObiRope in the scene view immediately after it's created.

[Image: 26omwRi.png]

So here's the result of me targeting a point in the level and trigger the above code. Looks good to me. Expected result: a rope is spawned matching the line exactly and then the rigidbody2d swings into the right wall.

The actual resulting rope starts looking correctly but then ends up being long enough for the rigidbody to continue falling and hit the ground. It's also oscillating between about -30 and 30 degrees every frame.

[Image: RIcjkje.png]

It's obvious I'm doing something wrong. Possibly parameters on the rope I'm not setting correctly, or maybe the tangents/normals when I set the initial path. Any tips? I could provide the scene if needed.

EDIT: Changing the solver mode to 'Mode 2D' improved it slightly but I'm still getting the oscillations and longer than expected ropes.

Hey, so I think I've managed to improve it a lot by imposing rotation constaints on the rigidbody and increasing the amount of substeps on the updater. It's working a lot more like what I need now!
Reply
#2
Using 2D mode for 2D physics is a must Guiño.

Even if all your initial particle positions are 0 in the z axis, the slightest numerical precision error can introduce non-zero values in the z axis resulting in unintended behavior. 2D mode actually skips the z component in all internal math operations, so that this can't ever happen. If you're using regular rigidbodies, constraining them to the XY plane is also a good idea because of the same reason.

Increasing the amount of substeps will greatly improve the quality of the simulation. See:
http://obi.virtualmethodstudio.com/tutor...gence.html
Reply