Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Generated rope with pin constraints
#1
Hello Jose and everybody in the community,

So far I'm using the Filo for hoist  simulations and am currently starting with Obi rope to simulate slings.
The features are truly impressive.
I am of course struggling with the mass ratio limitation of the iterative solver just as every other poster in this forum.

However, now I face a different problem.

I need to create slings at runtime to connect load to a hook.

I took the Grappling hook example and slightly modified it.
It casts a ray from the camera to the mouse pointer and attaches a rope between a hook (cube) and a load (cube) hit by the ray.

That part works fine. The generated rope is generated at correct position, the length is correct and it is attached to both game objects.

The problem is that the load cube must rotate around the point of attachment and it does not.
When the rope attaches to a side of the cube and gets retracted (which would normally roll the cube over)  the rope starts to move like a tentacle of an octopus suffering from epileptic seizure.

I use Unity 2019.3.1f1 and Obi Rope 5.3

A rope configured in the editor behaves correctly.



The rope is generated by this script:

Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Obi;

/**
* Sample component that shows how to use Obi Rope to create a grappling hook for a 2.5D game.
* 95% of the code is the grappling hook logic (user input, scene raycasting, launching, attaching the hook, etc) and parameter setup,
* to show how to use Obi completely at runtime. This might not be practical for real-world scenarios,
* but illustrates how to do it.
*
* Note that the choice of using actual rope simulation for grapple dynamics is debatable. Usually
* a simple spring works better both in terms of performance and controllability.
*
* If complex interaction is required with the scene, a purely geometry-based approach (ala Worms ninja rope) can
* be the right choice under certain circumstances.
*/
public class Sling : MonoBehaviour
{

   public ObiSolver solver;
   public ObiCollider hook;
   public float hookExtendRetractSpeed = 2;
   public Material material;
   public ObiRopeSection section;

   private ObiRope rope;
   private ObiRopeBlueprint blueprint;
   private ObiRopeExtrudedRenderer ropeRenderer;

   private ObiRopeCursor cursor;

   private RaycastHit hookAttachment;
   private bool attached = false;

   void Awake()
   {

       // Create both the rope and the solver:    
       rope = gameObject.AddComponent<ObiRope>();
       ropeRenderer = gameObject.AddComponent<ObiRopeExtrudedRenderer>();
       ropeRenderer.section = section;
       ropeRenderer.uvScale = new Vector2(1, 5);
       ropeRenderer.normalizeV = false;
       ropeRenderer.uvAnchor = 0;
       rope.GetComponent<MeshRenderer>().material = material;

       // Setup a blueprint for the rope:
       blueprint = ScriptableObject.CreateInstance<ObiRopeBlueprint>();
       blueprint.resolution = 1.0f;
       blueprint.thickness = 0.1f;

       // Tweak rope parameters:
       rope.maxBending = 0.02f;

       // Add a cursor to be able to change rope length:
       cursor = rope.gameObject.AddComponent<ObiRopeCursor>();
       cursor.cursorMu = 0;
       cursor.direction = true;
   }

   private void OnDestroy()
   {
       DestroyImmediate(blueprint);
   }

   /**
     * Raycast against the scene to see if we can attach the hook to something.
     */
   private void LaunchHook()
   {

       // Get the mouse position in the scene, in the same XY plane as this object:
       Vector3 mouse = Input.mousePosition;
       mouse.z = 100000.0f;
       Vector3 mouseInScene = Camera.main.ScreenToWorldPoint(mouse);

       // Get a ray from the camera to the mouse:
       Ray ray = new Ray(Camera.main.transform.position, mouseInScene);


       // Raycast to see what we hit:
       if (Physics.Raycast(ray, out hookAttachment))
       {
           // We actually hit something, so attach the hook!
           StartCoroutine(AttachHook());
       }

   }

   private IEnumerator AttachHook()
   {
       yield return 0;
       Vector3 localHit = rope.transform.InverseTransformPoint(hookAttachment.point);

       // Procedurally generate the rope path (a simple straight line):
       blueprint.path.Clear();
       blueprint.path.AddControlPoint(hook.transform.localPosition + Vector3.down * 0.6f, Vector3.up, Vector3.down, Vector3.up, 0.1f, 0.1f, 1, 1, Color.white, "Sling hook");
       blueprint.path.AddControlPoint(localHit, Vector3.up, Vector3.down, Vector3.up, 0.1f, 0.1f, 1, 1, Color.white, "Sling load");
       blueprint.path.FlushEvents();

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

       // Pin both ends of the rope (this enables two-way interaction between character and rope):
       var pinConstraints = blueprint.GetConstraintsByType(Oni.ConstraintType.Pin) as ObiConstraints<ObiPinConstraintsBatch>;
       var batch = pinConstraints.batches[0];
       batch.AddConstraint(0, hook, transform.localPosition + Vector3.down * 0.6f, Quaternion.identity);
       //batch.AddConstraint(blueprint.activeParticleCount - 1, hookAttachment.collider.GetComponent<ObiColliderBase>(), hookAttachment.collider.transform.InverseTransformPoint(hookAttachment.point), Quaternion.identity);
       batch.AddConstraint(blueprint.activeParticleCount - 1, hookAttachment.collider.GetComponent<ObiCollider>(), hookAttachment.transform.InverseTransformPoint(hookAttachment.point), Quaternion.identity);
       batch.activeConstraintCount = 2;

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

   private void DetachHook()
   {
       // Set the rope blueprint to null (automatically removes the previous blueprint from the solver, if any).
       rope.ropeBlueprint = null;
       rope.GetComponent<MeshRenderer>().enabled = false;
   }


   void Update()
   {

       if (Input.GetMouseButtonDown(0))
       {
           if (!rope.isLoaded)
               LaunchHook();
           else
               DetachHook();
       }

       if (rope.isLoaded)
       {
           if (Input.GetKey(KeyCode.W))
           {
               cursor.ChangeLength(rope.restLength - hookExtendRetractSpeed * Time.deltaTime);
           }
           if (Input.GetKey(KeyCode.S))
           {
               cursor.ChangeLength(rope.restLength + hookExtendRetractSpeed * Time.deltaTime);
           }
       }
   }
}


The hook cube has just a box collider and Obi collider, the load cube has also colliders and a Rigidbody component.
Rotation of the load cube is not frozen, its angular velocities are not zero, but are below 0.02 rad/s

Please let me know where I made a mistake.
Reply


Messages In This Thread
Generated rope with pin constraints - by pQuex - 07-05-2020, 01:21 PM