I am trying to make a configurableJoint act like a hinge in 2D.
I have a sphere that I am attaching to a static cube as a simple test.
It does not act springy.
I am currently using the arrows to give it local acceleration to make it swing faster/slower in either direction.
When you hit the space bar it frees the xMotion, yMotion and zMotion constraints and continues it’s current momentum no longer bound to the hinge effect.
This part all works fine. (well, except that after a certain speed of rotation it hits a jarring halt for no apparent reason)
However, the bigger issue is that I would like to allow the user to hit another key at any time and have it act like a hinge again, using it’s current distance as the new linearLimit and keeping it’s anchor at the same spot on the cube as before hinging with it’s new length. My attempt at this has obviously failed since after you hit the key it springs right back to the same distance between the cube and sphere as before and then continues swinging like a hinge as before. It’s like the linearLimit changes are being ignored.
Basically, I have a rigidBody sphere with a configurableJoint with the xMotion, yMotion and zMotion set to locked so it is not springy as well as angularXMotion and angularYMotion locked on the configurableJoint but leaving angularZMotion as free to be the hinge rotation.
I have a cube that is a rigidBody that the configurableJoint uses as the connectObject, with it’s isKinematic checked on to keep it from moving.(Since, apparently setting static and constraining all translation and rotation axis’ does not keep it static by itself in this scenario)
I addForce to the rigidBody of the sphere locally to transform.right when the Horizontal axis (left and right arrows) are used.
The space bar releases the hinge affect by setting the xMotion, yMotion and zMotion to free and the linearLimit.limit to 0 and JointProjectionMode to None.
The up arrow resets these values putting the xMotion, yMotion and zMotion back to locked and the linearLimit.limit as the current distance beween the sphere and the cube rigidBodies and set the JointProjection Mode back to Position Only.
I would attach my simple test project but I don’t see an option for attaching a zip file here.
The cube is called HingeGoal and is positioned at 0,0,0
It is set to Static and has isKinematic checked on and constrained all x,y, and z position and x,y, and z rotation
The sphere is positioned at 0,-5,0 has a rigidBody attached using default values and the script below attached.
The sphere has Z position constrained (to keep it in 2d)
Here are the attributes that are changed from the default ConfigurableJoint
Anchor = 0, 5, 0 //opposite of it’s position from default
XMotion = Locked
YMotion = Locked
ZMotion = Locked
angularXMotion = Locked
angularYMotion = Locked
AngularZMotion = Free
linearLimt = 0
projectionMode = PositionOnly
projectionDistance = 0.01
//Here’s my script attached to the sphere
var power : float = 30.0;
function Start ()
{
var hingeGoal = gameObject.Find (“HingeGoal”);
var jt : ConfigurableJoint = GetComponent("ConfigurableJoint");
jt.anchor = hingeGoal.transform.position - transform.position ;
var vecD : Vector3 = (transform.position - hingeGoal.transform.position);
var magD : float = vecD.magnitude;
jt.linearLimit.limit = magD;
}
function Update ()
{
var jt : ConfigurableJoint = GetComponent(“ConfigurableJoint”);
var rbody : Rigidbody = GetComponent("Rigidbody");
horz = Input.GetAxis("Horizontal");
if (horz)
{
Debug.Log("horiz");
//local lateral acceleration
rigidbody.AddForce(transform.right * horz * power);
//rigidbody.AddForce(horz*power, 0, 0 );
}
var hingeGoal = gameObject.Find ("HingeGoal");
if (jt.xMotion == 0)
{
Debug.DrawRay(transform.position, (hingeGoal.transform.position - transform.position ), Color.green);
}
//Release
space = Input.GetKey("space");
//release hinge affect
if (space)
{
//Debug.Log("Space!");
Debug.Log("jt.xMotion ="+jt.xMotion);
//if (jt.xMotion == ConfigurableJointMotion.Free)
if (jt.xMotion == ConfigurableJointMotion.Locked)
{
jt.linearLimit.limit = 0;//Vector3.Distance(rbody.transform.position, hingeGoal.transform.position);
Debug.Log("jt.xMotion ="+jt.xMotion);
jt.xMotion = 2;
jt.yMotion = 2;
jt.zMotion = 2;
jt.angularXMotion = 2;
jt.angularYMotion = 2;
jt.linearLimit.limit = 0;
jt.projectionMode = JointProjectionMode.None;
}
}
//Reattach
up = Input.GetKey("up");
if (up)
{
if (jt.xMotion == ConfigurableJointMotion.Free)
{
Debug.Log("jt.xMotion ="+jt.xMotion);
jt.linearLimit.limit = Vector3.Distance(rbody.transform.position, hingeGoal.transform.position);
jt.xMotion = 0;
jt.yMotion = 0;
jt.zMotion = 0;
jt.angularXMotion = 0;
jt.angularYMotion = 0;
jt.projectionMode = JointProjectionMode.PositionOnly;
}
}
}
So, Unity Coder Brains, any thoughts how to get this to work correctly?
=============================================================
“Unscrewing the joint” did the trick!
I also had to fix the anchor position by getting the cube’s position in the coordinate space of the sphere.
jt.anchor = transform.InverseTransformPoint(hingeGoal.transform.position);
Thanks Owen!