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

    JohnKheng

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

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,067
    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

    JohnKheng

    Joined:
    May 31, 2020
    Posts:
    3
    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

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,067
    JohnKheng likes this.
  5. JohnKheng

    JohnKheng

    Joined:
    May 31, 2020
    Posts:
    3
    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):
    1.  
    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.