Search Unity

How do I keep my joint from dragging its rigidbody through colliders?

Discussion in 'Scripting' started by Sendatsu_Yoshimitsu, Aug 11, 2020.

  1. Sendatsu_Yoshimitsu

    Sendatsu_Yoshimitsu

    Joined:
    May 19, 2014
    Posts:
    691
    I used https://gist.github.com/mstevenson/4552515 as the basis to build a really simple rigidbody drag & drop implementation, and 99% of the time it works great. However, if I carefully perch the object on its corner and drag the mouse far outside of its range of motion (so the joint is trying to pull it under/through the collider it's sitting on), the rigidbody will start vibrating aggressively and eventually slip through the collider or fly off into space. Massively increasing the damping value of the joint spring helps somewhat, but it's still a noticeable and jarring behavior that most people find within 30 seconds of playing around with it. Is there any obvious modification I can make to the joint to prevent this?

    Code (CSharp):
    1.     public float force = 600;
    2.     public float damping = 6;
    3.  
    4.     Transform jointTrans;
    5.     float dragDepth;
    6.  
    7.  
    8.  
    9.     public void OnBeginDrag(PointerEventData eventData)
    10.     {
    11.         var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    12.         RaycastHit hit;
    13.         if (Physics.Raycast(ray, out hit))
    14.         {
    15.             dragDepth = CameraPlane.CameraToPointDepth(Camera.main, hit.point);
    16.             jointTrans = AttachJoint(hit.rigidbody, hit.point);
    17.         }
    18.  
    19.     }
    20.  
    21.     public void OnDrag(PointerEventData eventData)
    22.     {
    23.  
    24.         if (jointTrans == null)
    25.             return;
    26.         Vector3 worldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    27.         jointTrans.position = CameraPlane.ScreenToWorldPlanePoint(Camera.main, dragDepth, Input.mousePosition);
    28.     }
    29.  
    30.  
    31.     public void OnEndDrag(PointerEventData eventData)
    32.     {
    33.         Destroy(jointTrans.gameObject);
    34.         jointTrans = null;
    35.     }
    36.  
    37.  
    38.  
    39.     Transform AttachJoint(Rigidbody rb, Vector3 attachmentPosition)
    40.     {
    41.         GameObject go = new GameObject("Attachment Point");
    42.         go.hideFlags = HideFlags.HideInHierarchy;
    43.         go.transform.position = attachmentPosition;
    44.  
    45.         var newRb = go.AddComponent<Rigidbody>();
    46.         newRb.isKinematic = true;
    47.  
    48.         var joint = go.AddComponent<ConfigurableJoint>();
    49.         joint.connectedBody = rb;
    50.         joint.configuredInWorldSpace = true;
    51.         joint.xDrive = NewJointDrive(force, damping);
    52.         joint.yDrive = NewJointDrive(force, damping);
    53.         joint.zDrive = NewJointDrive(force, damping);
    54.         joint.slerpDrive = NewJointDrive(force, damping);
    55.         joint.rotationDriveMode = RotationDriveMode.Slerp;
    56.  
    57.         return go.transform;
    58.     }
    59.  
    60.     private JointDrive NewJointDrive(float force, float damping)
    61.     {
    62.         JointDrive drive = new JointDrive();
    63.         //        drive.mode = JointDriveMode.Position;
    64.         drive.positionSpring = force;
    65.         drive.positionDamper = damping;
    66.         drive.maximumForce = 600;
    67.         return drive;
    68.     }
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    The physics system operates best when kept within a few orders of magnitude of forces, torques and offsets. Any more than that and it will become unstable. It is all computed with only single-precision floating point numbers, and they are very limited in terms of what they can express.

    When you are moving something extremely close to a pivot or lever, you can suddenly introduce enormous torques and forces, as the torque is the driving force divided by the lever arm and as the lever arm approaches zero, the torque can get very large.

    One approach is to simply keep actionable forces far away from known pivots and/or levers. Another approach is to have user input drive a separate forcing feature that only gradually begins to drive an object into place, with some upper limit on its ultimate force application.
     
  3. Sendatsu_Yoshimitsu

    Sendatsu_Yoshimitsu

    Joined:
    May 19, 2014
    Posts:
    691
    Hmkay that helps, thank you! :)