I have a composite GameObject with arms, legs, and head connected to a torso with hingejoint components. Each contains a non-kinematic rigidbody, collider, and is parented to a common empty GameObject. The mass for each rigidbody is exactly 1.
The colliders all exist on the same Layermask which is set to collide with itself. At original scale, the colliders do not overlap. Additionally, these GameObjects are linked to a prefab. All hinge joints are instantiated with a non-infinite breaking force.
When the local scale of the parent Transform is changed, the hinge joints break. This is observed when:
- The common Layermask is set to not collide with itself.
- When gravity is zero’d.
- When Instantiating the prefab programatically and immediately changing the localscale of the parent transform.
- When Instantiating the prefab from the editor and changing the localscale of the parent transform arbitrarily.
- When Instantiating the prefab, setting each rigidbody to kinematic, changing the localscale, advancing a frame, and setting each rigidbody back to non-kinematic.
- Setting break forces to infinity, setting localscale, setting break forces back to non-infinite values. Single frame operation.
On inspection, it appears that hinge joint anchors do not move when localscale is modified. This will account for the hingejoint breaks; transforms move, but they are expected to be in a previous location. The hingejoint will exert a force on itself in order to return to the expected position, but this force is enough to break some breaking forces. This is exacerbated with colliders and a increase in local scale; the hingejoints will need to move the joints to within a collider, which will probably result in massive forces. Think about that for a minute.
Originally, I was going to ask for ideas on how to avoid those breaks, but researching the issue seems to have given me some ideas. Regardless, I’ll submit this in case anyone else runs into the same issue, or has a better solution.
Proposed solution: During the frame where you adjust the localscale of a parent GameObject which contains hingejoints, scale the positions of the hingejoint anchors by the magnitude of the adjustment to the localscale. Assuming that this works, I will respond with confirmation. Else, frustration.
So, I tried out the anchor-adjustment strategy. Unfortunately, it doesn’t work. Kind-of. I’ve made some observations:
- If your Prefab is instantiated with the HingeJoints already attached and then local scale is changed, the break occurs. However, if your Prefab contains no pre-attached HingeJoints, but instead adds HingeJoints afterwards, the HingeJoints will not break after local scale is changed.
- If you recycle and reconstruct (put all the transforms back in the original positions, rotations, etc) the HingeJointed object (including recreating broken HingeJoints), your HingeJoints will not break when they have their local scale changed.
For clarity, adjusting the anchors of the HingeJoints doesn’t help at all. What matters is the difference between the positions of the transforms of the HingeJoint objects before and after the change to local scale. If the hinge joints don’t exist before the local scale is changed, then there can be no difference.