Skip to content

Instantly share code, notes, and snippets.

@mstevenson
Created October 24, 2014 07:14
Show Gist options
  • Star 68 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save mstevenson/7b85893e8caf5ca034e6 to your computer and use it in GitHub Desktop.
Save mstevenson/7b85893e8caf5ca034e6 to your computer and use it in GitHub Desktop.
Extension methods for working with Configurable Joints for Unity
using UnityEngine;
public static class ConfigurableJointExtensions
{
/// <summary>
/// Sets a joint's targetRotation to match a given local rotation.
/// The joint transform's local rotation must be cached on Start and passed into this method.
/// </summary>
public static void SetTargetRotationLocal (this ConfigurableJoint joint, Quaternion targetLocalRotation, Quaternion startLocalRotation)
{
if (joint.configuredInWorldSpace) {
Debug.LogError ("SetTargetRotationLocal should not be used with joints that are configured in world space. For world space joints, use SetTargetRotation.", joint);
}
SetTargetRotationInternal (joint, targetLocalRotation, startLocalRotation, Space.Self);
}
/// <summary>
/// Sets a joint's targetRotation to match a given world rotation.
/// The joint transform's world rotation must be cached on Start and passed into this method.
/// </summary>
public static void SetTargetRotation (this ConfigurableJoint joint, Quaternion targetWorldRotation, Quaternion startWorldRotation)
{
if (!joint.configuredInWorldSpace) {
Debug.LogError ("SetTargetRotation must be used with joints that are configured in world space. For local space joints, use SetTargetRotationLocal.", joint);
}
SetTargetRotationInternal (joint, targetWorldRotation, startWorldRotation, Space.World);
}
static void SetTargetRotationInternal (ConfigurableJoint joint, Quaternion targetRotation, Quaternion startRotation, Space space)
{
// Calculate the rotation expressed by the joint's axis and secondary axis
var right = joint.axis;
var forward = Vector3.Cross (joint.axis, joint.secondaryAxis).normalized;
var up = Vector3.Cross (forward, right).normalized;
Quaternion worldToJointSpace = Quaternion.LookRotation (forward, up);
// Transform into world space
Quaternion resultRotation = Quaternion.Inverse (worldToJointSpace);
// Counter-rotate and apply the new local rotation.
// Joint space is the inverse of world space, so we need to invert our value
if (space == Space.World) {
resultRotation *= startRotation * Quaternion.Inverse (targetRotation);
} else {
resultRotation *= Quaternion.Inverse (targetRotation) * startRotation;
}
// Transform back into joint space
resultRotation *= worldToJointSpace;
// Set target rotation to our newly calculated rotation
joint.targetRotation = resultRotation;
}
/// <summary>
/// Adjust ConfigurableJoint settings to closely match CharacterJoint behaviour
/// </summary>
public static void SetupAsCharacterJoint (this ConfigurableJoint joint)
{
joint.xMotion = ConfigurableJointMotion.Locked;
joint.yMotion = ConfigurableJointMotion.Locked;
joint.zMotion = ConfigurableJointMotion.Locked;
joint.angularXMotion = ConfigurableJointMotion.Limited;
joint.angularYMotion = ConfigurableJointMotion.Limited;
joint.angularZMotion = ConfigurableJointMotion.Limited;
joint.breakForce = Mathf.Infinity;
joint.breakTorque = Mathf.Infinity;
joint.rotationDriveMode = RotationDriveMode.Slerp;
var slerpDrive = joint.slerpDrive;
slerpDrive.mode = JointDriveMode.Position;
slerpDrive.maximumForce = Mathf.Infinity;
joint.slerpDrive = slerpDrive;
}
}
@sergioabreu-g
Copy link

Thanks! It was very useful :D

@PixHammer
Copy link

Thank you for this, I use it a lot. Absolute nightmare using target rotation usually.

@R3X-G1L6AME5H
Copy link

Used this a long while ago to set up 6DOF Joints in Godot. It worked there as well. Cheers, mate!

@SuJiaTao
Copy link

SuJiaTao commented Feb 1, 2023

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment