Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save chrisforbes/d04b0d6938cfb63c5df214e1411d5e71 to your computer and use it in GitHub Desktop.
Save chrisforbes/d04b0d6938cfb63c5df214e1411d5e71 to your computer and use it in GitHub Desktop.
using UnityEngine;
using System.Collections.Generic;
public class HandGrab : MonoBehaviour
{
SteamVR_TrackedObject trackedObj;
SteamVR_Controller.Device controller { get { return SteamVR_Controller.Input((int)trackedObj.index); } }
GameObject pickUp;
ConfigurableJoint joint, joint2;
public TextMesh describe;
void Start()
{
trackedObj = GetComponent<SteamVR_TrackedObject>();
pickUp = null;
}
Transform GetRoot(GameObject o)
{
var t = o.transform;
while (t.parent != null)
t = t.parent;
return t;
}
void OnTriggerEnter(Collider collider)
{
// don't consider anything that's in our hierarchy. we don't want the hands
// to collide with themselves, with each other, with the body, etc...
// DONT do this using collision layers - we don't know how many players there will be.
if (GetRoot(collider.gameObject) == GetRoot(gameObject))
return;
// don't consider things that are not rigid bodies. we /might/ be able to fix this in future
// to use layers.
if (collider.gameObject.GetComponent<Rigidbody>() == null)
return;
pickUp = collider.gameObject;
}
void OnTriggerExit(Collider collider)
{
if (pickUp == collider.gameObject)
pickUp = null;
}
void ConfigureJoint(float mass, bool driveRotation, ConfigurableJoint j)
{
var springFactor = 3000f;
var damperFactor = 10f;
var maxForceFactor = 70f;
var breakFactor = 150f;
JointDrive drive = j.xDrive;
drive.positionSpring = springFactor * mass;
drive.positionDamper = damperFactor * mass;
drive.maximumForce = maxForceFactor * mass;
j.xDrive = drive;
drive = j.yDrive;
drive.positionSpring = springFactor * mass;
drive.positionDamper = damperFactor * mass;
drive.maximumForce = maxForceFactor * mass;
j.yDrive = drive;
drive = j.zDrive;
drive.positionSpring = springFactor * mass;
drive.positionDamper = damperFactor * mass;
drive.maximumForce = maxForceFactor * mass;
j.zDrive = drive;
if (driveRotation)
{
var angularSpringFactor = 30f;
var angularDamperFactor = 1f;
j.rotationDriveMode = RotationDriveMode.XYAndZ;
drive = j.angularYZDrive;
drive.positionSpring = angularSpringFactor * mass;
drive.positionDamper = angularDamperFactor * mass;
j.angularYZDrive = drive;
drive = j.angularXDrive;
drive.positionSpring = angularSpringFactor * mass;
drive.positionDamper = angularDamperFactor * mass;
j.angularXDrive = drive;
}
j.breakForce = breakFactor * mass;
}
Vector3 grabPoint;
Quaternion grabOrientation;
void Update()
{
if (controller.GetPressDown(Valve.VR.EVRButtonId.k_EButton_Grip) && pickUp != null)
{
var rb = pickUp.GetComponent<Rigidbody>();
if (rb.isKinematic)
{
// this constraint will allow us to pull/push ourselves through the space.
var rootGameObject = GetRoot(gameObject).gameObject;
if (joint2 == null)
joint2 = rootGameObject.AddComponent<ConfigurableJoint>();
joint2.connectedBody = null;
joint2.anchor = transform.localPosition;
grabPoint = transform.localPosition;
grabOrientation = transform.localRotation;
joint2.connectedAnchor = new Vector3(0, 0, 0);
joint2.autoConfigureConnectedAnchor = false;
joint2.configuredInWorldSpace = false;
ConfigureJoint(rootGameObject.GetComponent<Rigidbody>().mass, true, joint2);
}
else
{
// this constraint will allow us to hold a free object.
if (joint == null)
joint = gameObject.AddComponent<ConfigurableJoint>();
joint.connectedBody = rb;
ConfigureJoint(rb.mass, true, joint);
}
}
if (joint2 != null)
{
joint2.targetPosition = transform.localPosition - grabPoint;
joint2.targetRotation = transform.localRotation * Quaternion.Inverse(grabOrientation);
}
if (controller.GetPressUp(Valve.VR.EVRButtonId.k_EButton_Grip))
{
if (joint != null)
{
Destroy(joint);
joint = null;
}
if (joint2 != null)
{
Destroy(joint2);
joint2 = null;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment