- Home /
Creating draggable hinge joint
Hello everyone.
I am using 2D mode of editor. I have createt two sprites: one long rectangle, second is short rectangle. I have attached to both of them BoxCollider2D's and rigidbodies.
I have made square rigidbody kinematic. After that, I have added to rectangle Hinge joint and connected it with rigidbody of square.
So i have rectangle that is fixed at square and spins around it when other objects will hit it.
Question: How can I make this carousel controllable with touch and mouse, like if I start to drag it, it will rotate to position of my touch/mouse? Also when I release it, it will rotate with speed of my last swipe and start to slow down until it stops.
PS. Gravity is zero.
Answer by slek120 · Apr 05, 2014 at 01:47 PM
You can use the DragRigidBody2D script Here is my version of the script
using UnityEngine;
using System.Collections;
public class DragRigidBody2D : MonoBehaviour
{
public float distance = 0.2f;
public float dampingRatio = 1;
public float frequency = 1.8f;
public float linearDrag = 1.0f;
public float angularDrag = 5.0f;
private SpringJoint2D springJoint;
void Start ()
{
if (!springJoint) {
GameObject go = new GameObject ("Rigidbody2D Dragger");
Rigidbody2D body = go.AddComponent ("Rigidbody2D") as Rigidbody2D;
springJoint = go.AddComponent ("SpringJoint2D") as SpringJoint2D;
body.isKinematic = true;
}
}
// Update
void Update ()
{
if (!Input.GetMouseButtonDown (0))
return;
Camera mainCamera = FindCamera ();
int mask = (1 << 8);
RaycastHit2D hit = Physics2D.Raycast (mainCamera.ScreenToWorldPoint (Input.mousePosition), Vector2.zero, Mathf.Infinity, mask);
// I have proxy collider objects (empty gameobjects with a 2D Collider) as a child of a 3D rigidbody - simulating collisions between 2D and 3D objects
// I therefore set any 'touchable' object to layer 8 and use the layerMask above for all touchable items
if (hit.rigidbody != null && hit.rigidbody.isKinematic == true) {
return;
}
if (hit.rigidbody != null && hit.rigidbody.isKinematic == false) {
springJoint.transform.position = hit.point;
springJoint.dampingRatio = dampingRatio;
springJoint.frequency = frequency;
springJoint.distance = distance;
springJoint.connectedBody = hit.rigidbody;
// maybe check if the 'fraction' is normalised. See http://docs.unity3d.com/Documentation/ScriptReference/RaycastHit2D-fraction.html
StartCoroutine ("DragObject", hit.fraction);
} // end of hit true condition
} // end of update
IEnumerator DragObject (float distance)
{
float oldDrag = springJoint.connectedBody.drag;
float oldAngularDrag = springJoint.connectedBody.angularDrag;
springJoint.connectedBody.drag = linearDrag;
springJoint.connectedBody.angularDrag = angularDrag;
Camera mainCamera = FindCamera ();
while (Input.GetMouseButton (0)) {
Ray ray = mainCamera.ScreenPointToRay (Input.mousePosition);
springJoint.transform.position = ray.GetPoint (distance);
yield return null;
}
if (springJoint.connectedBody) {
springJoint.connectedBody.drag = oldDrag;
springJoint.connectedBody.angularDrag = oldAngularDrag;
springJoint.connectedBody = null;
}
}
Camera FindCamera ()
{
if (camera)
return camera;
else
return Camera.main;
}
}
Not working. I want for HingeJoint2D not SpringJoint2D. Even when I changed to SpringJoint2D it does not work.
You don't have to change anything you have. DragRigidBody2D makes a kinematic rigidbody2D with a springJoint2D component. If you click a rigidbody, it will connect the springJoint to that rigidbody. Then you can pull it by moving the mouse. This also translates to touch without changing any code.
One problem with the previous script is that it connects to the center of the connected rigidbody. $$anonymous$$aybe this is why it did not work. Try adding this around line 50.
springJoint.connectedAnchor = hit.transform.InverseTransformPoint (hit.point);
I have added this line, it is still does not work. I click this object, try to drag it, it just frozen to its place.
Oh, I'm sorry. There is a layer mask in the RaycastHit2D. This way, you can configure only certain objects to be draggable. To fix this, you can change line 32 to the number of the layer that the object is on (default = 0) or you can change line 33 to
RaycastHit2D hit = Physics2D.Raycast (mainCamera.ScreenToWorldPoint (Input.mousePosition), Vector2.zero);
Does this fix your problem? Tell me if it doesn't.