Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Resolved Hinge Joint won't stay in place when moving GameObject

Discussion in 'Scripting' started by JohnKheng, Aug 13, 2021.

  1. JohnKheng


    May 31, 2020
    I'm trying to simulate a classic pendulum science experiment on unity.
    So just for a prototype, I attach a hinge joint on my weight(pendulum) with a connected body of a gameObject(anchor).
    Everything works fine until I try to move the weight programmatically.
    It seems like whenever I tried to move the mass, the hinge joint anchor won't stay in place. I'm not sure if this is a physics problem or scripting problem.
    I checked the inspector and the anchor axis doesn't seemed to change.
    Below is the GIF of my problem, and a script of how I move my weight programmatically.
    The red circle shows the anchor not staying in place when i click or move the weight, and the grey circle is just a guide of where the anchor should be.

    Sequence 02_1.gif

    Code (CSharp):
    1.     void OnMouseDown() {
    2.         gameObject.GetComponent<Rigidbody>().isKinematic = true;
    3.         //destroyJoint();
    4.         UpdateAnchorControlPlane();
    5.         UpdatePendulumPosition();
    6.     }
    8.     void OnMouseDrag() {
    9.         UpdatePendulumPosition();
    10.     }
    12.     private void OnMouseUp()
    13.     {
    14.         //recreateJoint();
    15.         gameObject.GetComponent<Rigidbody>().isKinematic = false;
    16.     }
    18.     void UpdateAnchorControlPlane() {
    19.         Vector3 anchorPos = anchorTransf.position;
    20.         anchorControlPlane.Set3Points(anchorPos + Vector3.forward, anchorPos + Vector3.up, anchorPos + Vector3.back);
    21.     }
    23.     void UpdatePendulumPosition() {
    24.         Vector3 anchorPosition = anchorTransf.position;
    25.         Vector3 posDifference = GetPlanePoint(Input.mousePosition) - anchorPosition;
    26.         posDifference = ClampToMagnitude(posDifference, minPower, maxPower);
    28.         pendulumTransf.transform.position = anchorPosition + posDifference;
    29.         pendulumTransf.transform.LookAt(anchorPosition, Vector3.left);
    30.     }
    32.     Vector3 GetPlanePoint(Vector3 pos) {
    33.         float distance;
    35.         Ray ray = cam.ScreenPointToRay(pos);
    36.         if(anchorControlPlane.Raycast(ray, out distance)) {
    37.             return ray.GetPoint(distance);
    38.         }
    40.         return pos;
    41.     }
    Can anyone please tell me how can I fix this? Thanks
  2. Kurt-Dekker


    Mar 16, 2013
    Manipulating the transform directly bypasses the physics engine (lines 28 and 29 above).

    When you have a Rigidbody, only use the .MovePosition() and .MoveRotation() methods on the RB instance.
    JohnKheng likes this.
  3. JohnKheng


    May 31, 2020
    First of, thanks. I tried changing it to move the RB and it works. The anchor now stays in place.

    But, I have another problem that came up. The pendulum works fine, but when it's rotation or the swinging angle reach somewhere about 1 to 2 degree, it began to swing all over the place like below.
    I not sure how to fix this as there is no script that changes or update the weight's position and rotation. I just use unity's hinge joint and gravity to do its work.
    This problem is consistent to happen when the swinging angle is less than 2 degree and when it is about to stop.
    Sequence 02.gif
  4. Kurt-Dekker


    Mar 16, 2013
    JohnKheng likes this.
  5. JohnKheng


    May 31, 2020
    Thanks a lot kurt. I found out the problem, it seemed like I put the wrong axis on the Quaternion.Euler as (x, y ,x) instead of x,y,z.

    Really appreciate the help though. And Thank you.!

    For those that wonder how I change from manipulating the transform.position to manipulating the rigidbody, here's the modification

    1. Change line 28 for position (code above) to:
    pendulumTransf.GetComponent<Rigidbody>().MovePosition(anchorPosition + posDifference);

    2. Change line 29 for rotation to a function:
    Code (CSharp):
    2.     void lookAt()
    3.     {
    4.         var localTarget = transform.InverseTransformPoint(anchor.transform.position);
    5.         float angle = traceAngle.transform.eulerAngles.x - 90f;
    6.         if (transform.position.z > 0) angle *= -1;
    7.         Vector3 eulerAngleVelocity = new Vector3(angle, 0, 0);
    8.         Quaternion deltaRotation = Quaternion.Euler(eulerAngleVelocity);
    9.         pendulumTransf.GetComponent<Rigidbody>().MoveRotation(Quaternion.AngleAxis(angle, Vector3.left));
    10.     }

    Really big thanks to Kurt-Dekker with the swift response and help!
    Kurt-Dekker likes this.