- Home /
ConfigurableJoint Object snaps back to old position when AngularMotion locked
I'm working in Unity3D version 4.
--- In a Nutshell---
Two objects.
A ConfigurableJoint is created between them with Motionx/y/z and angularMotionx/y/z locked so their relative positions to each other doesn't change.
OnMouseDrag changes angularMotionx/y/z to "Free"
User drags one object around the other.
When user releases mouse, I simply set the ConfigurableJoint's angularMotionx/y/z BACK to locked.
DESIRED OUTCOME: The objects stay in their new positions, and the configged joint is again locked so the two objects won't move in relation to each other (staying where the user put them).
ACTUAL OUTCOME: The objects snap back to the original relative position they were in when the joint was made.
--- DETAILS --- I have two objects attached by a configurable joint. When the objects are NOT interacting with the user, I want the joint to constrain their relative postition to each other. I accomplish this by setting the ConfigurableJoint's motionX/Y/Z and angularMotionX/Y/Z to "Locked".
However, I also want the user to be able to drag the objects around RELATIVE to each other.
I tried to accomplish this by setting the ConfigurableJoint's angular-motion to "Free" when one of the objects is being dragged around, and then setting it BACK to Locked when the user stops dragging on object.
But when I release the object, and re-lock the angular motion - the object snaps back to its original position.
private ConfigurableJoint MakeConfigurableJoint(Collider other, int end)
{
Vector3 myAnchor;
ConfigurableJoint tempJoint = this.gameObject.AddComponent("ConfigurableJoint") as ConfigurableJoint; // Neg
tempJoint.autoConfigureConnectedAnchor = false; // Prevent joint from finding it's own position
myAnchor = new Vector3(1f, 0, 0);
connectedBody1 = other.gameObject;
connectedBody1Script = connectedBody1.GetComponent<AtomScript>() as AtomScript;
tempJoint.anchor = myAnchor;
tempJoint.connectedBody = other.transform.rigidbody;
tempJoint.connectedAnchor = new Vector3(0, 0, 0);
// PARAMETERS //
// Motion
tempJoint.xMotion = ConfigurableJointMotion.Locked;
tempJoint.yMotion = ConfigurableJointMotion.Locked;
tempJoint.zMotion = ConfigurableJointMotion.Locked;
tempJoint.angularXMotion = ConfigurableJointMotion.Locked;
tempJoint.angularYMotion = ConfigurableJointMotion.Locked;
tempJoint.angularZMotion = ConfigurableJointMotion.Locked;
tempJoint.axis = new Vector3(0, 0, 0);
tempJoint.secondaryAxis = new Vector3(0,0,0);
return tempJoint;
}//MakeConfigurableJoint
// This DOES successfully allow me to move the object around the other
public void loosenBonds()
{
tempJoint.angularXMotion = ConfigurableJointMotion.Free;
tempJoint.angularYMotion = ConfigurableJointMotion.Free;
tempJoint.angularZMotion = ConfigurableJointMotion.Free;
}// loosenBonds
// This DOES lock the movement again, but first it snaps the object back to the original location (doesn't leave it where I dragged it)
public void tightenBonds()
{
tempJoint.angularXMotion = ConfigurableJointMotion.Locked;
tempJoint.angularYMotion = ConfigurableJointMotion.Locked;
tempJoint.angularZMotion = ConfigurableJointMotion.Locked;
}// tightenBonds
void OnMouseDown(){ loosenBonds() };
void OnMouseUp() { tightenBonds(); }
This question is highly relevant to anyone desiring to emulate hydraulics using Unity/PhysX. The intuitive model for hydraulics is that a joint is driven by forces when active and is locked when inactive.
We have had to resort to using very high force levels combined with very high damping (or perhaps drag) levels combined with limiting ourselves to fairly slow target velocities. Otherwise our rig behaves like an assembly of soggy noodles. (We do taste this hack is going to catch up with us later.)
So: we also want exactly what the OP wants, which is to be able to dynamically lock a joint axis in its current position.
Answer by dwaldrum · Jan 22, 2017 at 09:44 PM
The proper way to do this is to actually change from using desired velocity to desired rotation in order to lock the joint.
So when you start driving the joint with a force, you unlock the joint:
JointDrive drive = joint.angularXDrive;
drive.positionSpring = 0.0f;
drive.positionDamper = 50000.0f;
drive.targetAngularVelocity = new Vector3(1.0f, 0.0f, 0.0f);
joint.angularXDrive = drive;
Once you stop wanting to move the joint you then lock the joint:
joint.targetRotation = GetCurrentRotation(joint);
joint.targetAngularVelocity = new Vector3(0.0f, 0.0f, 0.0f);
JointDrive drive = joint.angularXDrive;
drive.positionSpring = 50000.0f;
drive.positionDamper = 0.0f;
joint.angularXDrive = drive;
The good thing about this is it gives your joint a realistic strength to its locking mechanism, depending on what you set your spring values to upon locking it can still react to forces and weights being applied.
Answer by Shiro_Yami · Feb 22, 2018 at 03:59 PM
Hi @dwaldrum, How can you get the current rotation of the joint please ?
Your answer
Follow this Question
Related Questions
In script, how to set ConfigurableJointMotion to locked without it reseting to default position 3 Answers
How do I set up a ConfigurableJoint so that it behaves just like a HingeJoint? 1 Answer
ConfigurableJoint to constrain objects to a straight track 0 Answers
consecutive angularxdrive.positionspring.equals() not working 0 Answers
angular limits 2 Answers