| 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; | |
| } | |
| } |
Nevermind, i was using connectedBody rotation, instead of direct parent. This works perfectly fine for setting world target on local joints:
public static void SetTargetRotation(this ConfigurableJoint cj, Quaternion startRot, Quaternion target, Space space)
{
Vector3 right = cj.axis;
Vector3 forward = Vector3.Cross(cj.axis, cj.secondaryAxis).normalized;
Vector3 up = Vector3.Cross(forward, right).normalized;
Quaternion localToJointSpace = Quaternion.LookRotation(forward, up);
if (space == Space.World)
{
Quaternion worldToLocal = Quaternion.Inverse(cj.transform.parent.rotation);
target = worldToLocal * target;
}
cj.targetRotation = Quaternion.Inverse(localToJointSpace) * Quaternion.Inverse(target) * startRot * localToJointSpace;
}Your script works fine for performing a single rotation, but i always have trouble implementing it in FixedUpdate(). I get the error:
"Skipped updating the transform of this Rigidbody because its components are infinite. Could you have applied infinite forces, acceleration or set huge velocity?"
void Awake() {
Quaternion startRotation = arm.transform.rotation;
joint = arm.GetComponent<ConfigurableJoint>();
}
void FixedUpdate() {
joint.SetTargetRotation(Quaternion.Euler(0, 0.01f, 0), startRotation);
}
I just want to rotate the joint consistently along its joints y-axis. Im currently getting headaches over the simplest tasks using ConfigurableJoints :))
Thanks for any help in advance!
Nevermind, was my mistake. The problem was that i redefined "startRotation" to be a quaternion in the Awake() call, so always go the default Quaternion value for "startRotation" in FixedUpdate()
That's so coool!!!!
Can I request that you add an additional method here to return the Local/World space rotation of the joint's targetRotation? I'm trying to Slerp a joint's targetRotation through to a new orientation but I need to know it's current orientation first.
public static Quaternion GetTargetRotation(ConfigurableJoint joint, Quaternion startRotation, Space space) { ... }
Thanks
Hey @mstevenson, Quick question with the "StartRotation" quaternion. Is this the local rotation (Global, if not a child to anything) of the transform that the joint is created on at the time of joint-creation? Is this ever updated if connected bodies, anchors, etc change?
So is there no way of setting the world-space target on local-configured joint? Ive tried rotating the target to inverse parent rotation, but it doesnt seem to be correct. Any ideas?