Search Unity

HingeJoint2D Behavior when reattaching joints at runtime

Discussion in 'Physics' started by Coder4Coffee, Jun 9, 2020.

  1. Coder4Coffee

    Coder4Coffee

    Joined:
    Jul 16, 2017
    Posts:
    1
    Hi there,

    I'm trying to use Unity2D HingeJoint2D functionality to connect pieces of a snakes body together for snake like movement.

    My General Heirarchy looks like this:
    https://imgur.com/JM9NqIC

    Where several snake body pieces exist between the head and tail and all pieces have a single HingeJoint2D connecting to the piece 1 closer to the head (and the head does not have one). The head has force applied to it which, with the physics applied by the HingeJoints, allows for snake like movement.

    1 Feature I wish for this Entity to have is to be able to grow and shrink on demand by removing a body piece or adding a body piece at run time. I do this mostly successfully by instantiating a new body piece inbetween the tail and 2nd to last piece, or Destroying this piece and reconnecting the hinge joints to point to the correct joint.
    Example of it working in action:
    https://i.imgur.com/XIRnhoB.gif

    My issues lies in what appears to be a corner case where sometimes when I add a new piece and restitch the HingeJoint2Ds together, the pieces that were reattached will rotate the opposite direction (sometimes multiple full 360s even). A basic case of this occurring can be seen here:
    https://i.imgur.com/Wo1V2NH.gif

    From observation, I've noticed I have no issues unless the snake rotates a full phase of a circle around, after which 1 newly added part does this strange rotation behavior.

    Example where I first show normal growth, then I walk in one circle and the tail spins in 1 circle the opposite direction. I pause movement specifically (head velocity = 0) at the time of growth
    https://i.imgur.com/sa5aw5u.gif:

    Another example where the snake moves in 3 circles then movement is paused for growth and the tail rotates in the opposite direction for 3 full rotations:
    https://i.imgur.com/dpPsfNf.gif

    I have verified that at the time of instantiation the rotations of all snake pieces are all correct/reasonable but immediately after being spawned in the HingeJoint2D of the recently added piece seems to rotate it.

    My Question is what's going on here as it only occurs in this corner case? Can anyone help me understand and hopefully find a solution to why this is occurring?

    My Joint Setting code:
    Code (CSharp):
    1.     public void AttachNewJoint(GameObject to_attach,  Rigidbody2D connected_body, float anchor_distance) {
    2.         HingeJoint2D hinge = to_attach.GetComponent<HingeJoint2D>();
    3.         hinge.autoConfigureConnectedAnchor = false;
    4.         hinge.useLimits = false;
    5.         hinge.anchor = new Vector2(0, 0);
    6.         hinge.connectedAnchor = new Vector2(0, anchor_distance);  
    7.         hinge.connectedBody = connected_body;
    8.         hinge.limits = joint_limits;
    9.         hinge.useLimits = true;
    10.         hinge.autoConfigureConnectedAnchor = true;          //I've tried with this enabled and disabled
    11.     }
    The value of joint_limits is -20, 20 degrees (defined as public variable for class).

    My Joint Removal/Unsetting code:
    Code (CSharp):
    1. public void RemoveJoint(GameObject to_remove) {
    2.         HingeJoint2D hinge = to_remove.GetComponent<HingeJoint2D>();
    3.         hinge.autoConfigureConnectedAnchor = false;
    4.         hinge.connectedBody = null;
    5. }
    The sudo code for adding a part is:
    Code (CSharp):
    1. RemoveTailJoint()
    2. DetermineSpawnPosAndRotationOfNewBody()
    3. Spawn()
    4. AttachNewJoint(tail)
    5. AttachNewJoint(new_spawn)
    The sudo code for removing a part is:
    Code (CSharp):
    1. RemoveTailJoint()
    2. Remove2ndListJoint()
    3. SetNewTailPosAndRotation()
    4. AttachNewJointTail()
    5. DestroyRemovedPart()