IsKinematicenabled if you don't want it to act like a physics object.
HingeJointdoes not constrain the absolute
localRotationof the Transform that it is attached to. It constrains the relative rotation between its own RigidBody and the Rigidbody in the
HingJoint.axisdo not represent the rotation of the Transform that it is attached to. Ex:
Quaternion.AngleAxis(hinge.angle, hinge.axis) // is *not* equivalent to either of hinge.transform.rotation hinge.transform.localRotation
To quote the official docs:
The rest angle between the bodies is always zero at the beginning of the simulation.
The consequence of this is that
HingeJoint.angle does not depend on the starting orientation of the joint's
RigidBody or the connected
RigidBody. And because
HingeJoint.limits represents limits on
HingeJoint.angle, the limits are also independent of any starting orientation of the bodies.
An example: Consider a
GameObject with rotation
(0, 0, 0) and a
HingeJoint on the x-axis with limits of
[-90, 90]. When played as-is, this
GameObject will be free to rotate between
(-90, 0, 0) and
(90, 0, 0). However, if you rotate this
GameObject in the editor such that it starts with rotation
(90, 0, 0) and play it, the
GameObject will then be free to rotate between
(0, 0, 0) and
(180, 0, 0) - even though the angle limits have not changed.
In most cases,
HingeJoint should have a
ConnectedBody assigned. If left empty it causes your
HingeJoint to be anchored to the global physics coordinate system. If your
HingeJoint is the child of an object that moves, the joint will apply its limits within the global physics coordinate system - not in the joint's local coordinate system.
To ensure that your
HingeJoint behaves nicely, create a
RigidBody on the parent object and set that as the
ConnectedBody.1) In this configuration, the
angle of the
HingeJoint will correspond to the
localRotation of the
Transform 2). This makes the joint behavior much easier to reason about!