Making hands that physically interact with the world is easy. Making hands that feel “tight,” don’t jitter, and allow for climbing without custom physics code is the real challenge. This tutorial covers using Unity’s Configurable Joint as a high-performance PD controller.
While you can write a manual PID (Proportional-Integral-Derivative) loop to set velocities, it’s often overkill and hard to tune. We use a PD Controller (Skipping the ‘I’ because we don’t want integral wind-up in VR) which Unity’s ConfigurableJoint implements natively via JointDrives.
ConfigurableJoint to the Hand, and set the Connected Body to your Player Body.Standard joint drives use targetPosition and targetRotation. But if you want them to be rock-solid, you must provide Target Velocity.
By providing these, the physics solver knows not just where the hand wants to be, but how fast it’s moving to get there.
public class PhysicsHand : MonoBehaviour {
public Rigidbody body;
public Transform target; // The Controller
private ConfigurableJoint joint;
void FixedUpdate() {
// 1. Position tracking
joint.targetPosition = body.transform.InverseTransformPoint(target.position);
// 2. Velocity (The "D" in PD)
// High-school physics: Velocity = Change in Position / Time
Vector3 worldVelocity = (target.position - lastPosition) / Time.fixedDeltaTime;
joint.targetVelocity = body.transform.InverseTransformVector(worldVelocity);
// 3. Rotational tracking (Shortest path)
Quaternion rotationDiff = target.rotation * Quaternion.Inverse(body.rotation);
joint.targetRotation = Quaternion.Inverse(rotationDiff);
lastPosition = target.position;
}
}
The beauty of using a ConfigurableJoint is Newton’s Third Law.
Result: You get climbing for free. No “ClimbingState” logic needed—the physics engine handles the inverse force naturally.
rb.inertiaTensor = Vector3.one * 0.01f;.Linear Limit to prevent the hand from stretching like Inspector Gadget.Physics.defaultSolverIterations to 10+ for a “tighter” feel in VR.