Last active
April 22, 2025 13:06
-
-
Save mstevenson/4958837 to your computer and use it in GitHub Desktop.
Unity extension methods for computing a ConfigurableJoint.TargetRotation value from a given local or world rotation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
Pls help me.
public class TheropodJointAngleCopy : MonoBehaviour
{
[Header("Left Foot Transform")]
public Transform tibiaLRef;
public Transform fibulaLRef;
public Transform footLRef;
public Transform footL2Ref;
[Header("Right Foot Transform")]
public Transform tibiaRRef;
public Transform fibulaRRef;
public Transform footRRef;
public Transform footR2Ref;
[Header("Arm Transform")]
public Transform upperArmLRef;
public Transform lowerArmLRef;
public Transform upperArmRRef;
public Transform lowerArmRRef;
[Header("Head & Neck Transform")]
public Transform neckRef;
public Transform neck2Ref;
public Transform headRef;
public Transform jawRef;
[Header("Spine Transform")]
public Transform frontSpineRef;
[Header("Tail Transform")]
public Transform tail1Ref;
public Transform tail2Ref;
public Transform tail3Ref;
public Transform tail4Ref;
public Transform tail5Ref;
[Header("Left Foot Joint")]
public ConfigurableJoint tibiaL;
public ConfigurableJoint fibulaL;
public ConfigurableJoint footL;
public ConfigurableJoint footL2;
[Header("Right Foot Joint")]
public ConfigurableJoint tibiaR;
public ConfigurableJoint fibulaR;
public ConfigurableJoint footR;
public ConfigurableJoint footR2;
[Header("Arm Joint")]
public ConfigurableJoint upperArmL;
public ConfigurableJoint lowerArmL;
public ConfigurableJoint upperArmR;
public ConfigurableJoint lowerArmR;
[Header("Head & Neck Joint")]
public ConfigurableJoint neck;
public ConfigurableJoint neck2;
public ConfigurableJoint head;
public ConfigurableJoint jaw;
[Header("Spine Joint")]
public ConfigurableJoint frontSpine;
[Header("Tails Joint")]
public ConfigurableJoint tail1;
public ConfigurableJoint tail2;
public ConfigurableJoint tail3;
public ConfigurableJoint tail4;
public ConfigurableJoint tail5;
public bool old;
private Dictionary<ConfigurableJoint, Quaternion> startRotations = new Dictionary<ConfigurableJoint, Quaternion>();
private void Awake()
{
// Lưu lại startRotation của từng joint
SaveStartRotation(tibiaL);
SaveStartRotation(fibulaL);
SaveStartRotation(footL);
SaveStartRotation(footL2);
SaveStartRotation(tibiaR);
SaveStartRotation(fibulaR);
SaveStartRotation(footR);
SaveStartRotation(footR2);
SaveStartRotation(upperArmL);
SaveStartRotation(lowerArmL);
SaveStartRotation(upperArmR);
SaveStartRotation(lowerArmR);
SaveStartRotation(neck);
SaveStartRotation(neck2);
SaveStartRotation(head);
SaveStartRotation(jaw);
SaveStartRotation(frontSpine);
SaveStartRotation(tail1);
SaveStartRotation(tail2);
SaveStartRotation(tail3);
SaveStartRotation(tail4);
SaveStartRotation(tail5);
}
private void SaveStartRotation(ConfigurableJoint joint)
{
if (joint != null)
{
startRotations[joint] = joint.transform.localRotation;
}
}
private void FixedUpdate()
{
ApplyAllJointRotations();
}
private void ApplyAllJointRotations()
{
ApplyJointRotation(tibiaL, tibiaLRef);
ApplyJointRotation(fibulaL, fibulaLRef);
ApplyJointRotation(footL, footLRef);
ApplyJointRotation(footL2, footL2Ref);
ApplyJointRotation(tibiaR, tibiaRRef);
ApplyJointRotation(fibulaR, fibulaRRef);
ApplyJointRotation(footR, footRRef);
ApplyJointRotation(footR2, footR2Ref);
ApplyJointRotation(upperArmL, upperArmLRef);
ApplyJointRotation(lowerArmL, lowerArmLRef);
ApplyJointRotation(upperArmR, upperArmRRef);
ApplyJointRotation(lowerArmR, lowerArmRRef);
ApplyJointRotation(neck, neckRef);
ApplyJointRotation(neck2, neck2Ref);
ApplyJointRotation(head, headRef);
ApplyJointRotation(jaw, jawRef);
ApplyJointRotation(frontSpine, frontSpineRef);
ApplyJointRotation(tail1, tail1Ref);
ApplyJointRotation(tail2, tail2Ref);
ApplyJointRotation(tail3, tail3Ref);
ApplyJointRotation(tail4, tail4Ref);
ApplyJointRotation(tail5, tail5Ref);
}
public void ApplyJointRotation(ConfigurableJoint joint, Transform refTransform)
{
if (joint == null || refTransform == null || !startRotations.ContainsKey(joint)) return;
joint.targetRotation = Quaternion.LookRotation(refTransform.localPosition);
Quaternion targetRotation = Quaternion.Inverse(refTransform.localRotation);
joint.targetRotation = targetRotation;
//Lấy góc quay mong muốn dựa trên Transform tham chiếu
//Quaternion targetRotation = refTransform.localRotation;
// Lấy góc quay ban đầu của khớp
//Quaternion startRotation = startRotations[joint];
//Quaternion targetRotation = /*Quaternion.Inverse(startRotation) **/ refTransform.localRotation;
//joint.SetTargetRotationLocal(targetRotation, startRotation); // if i set like this my TRex will wrong
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you very much! You saved my day