Menu

VR_Hand C#

Davide Enea Roberto Bobby Riva

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class VR_Hand : MonoBehaviour {
public Animator animator;

public enum WhichHands { Left, Right };
public WhichHands whichHand;

private GameObject hand;
private Transform shoulder;
public Transform handTarget;
private Transform cHandTarget;
private Vector3 dPalm;

public float thumbInput;
public float indexInput;
public float middleInput;
public float ringInput;
public float littleInput;

private Thumb thumb;
private Finger indexFinger;
private Finger middleFinger;
private Finger ringFinger;
private Finger littleFinger;

private Digit[] digits;

private GameObject grabbedObject = null;
private Rigidbody grabbedRigidbody = null;
private GrabbedRigidbody grabbedRBfunc;

private Collider collidedObject;

private Vector3 palmOffset;
private GameObject go;

void OnCollisionStay (Collision otherCollider) {
    Transform thisTransform, otherTransform;

    if (grabbedObject == null) {
        bool fingersCollided = false;
        bool thumbCollided = false;

        int ncontacts = otherCollider.contacts.Length;
        for (int i = 0; i < ncontacts; i++ ) {
            thisTransform = otherCollider.contacts[i].thisCollider.transform;
            otherTransform = otherCollider.contacts[i].otherCollider.transform;
            if (thisTransform == thumb.transform || otherTransform == thumb.transform)
                thumbCollided = true;
            for (int j = 1; j < digits.Length; j++) {
                Finger finger = (Finger) digits[j];
                if (thisTransform == finger.transform || otherTransform == finger.transform) {
                    fingersCollided = true;
                }
            }
        }

        bool grabbed = false;

        if (fingersCollided && thumbCollided) {
            for (int j = 1; j < digits.Length; j++) {
                Finger finger = (Finger) digits[j];
                if (finger.input > 0 && !finger.hasGrabbed()) {
                    finger.Grab();

                    if (!grabbed) {
                        grabbedObject = otherCollider.gameObject;
                        grabbedRigidbody = otherCollider.collider.attachedRigidbody;
                        Grab (grabbedObject, grabbedRigidbody);
                        grabbed = true;
                    }
                }
            }
        }
    }
}

void Grab(GameObject obj, Rigidbody rb) {
    Vector3 palmOffsetWorld = hand.transform.TransformDirection(palmOffset);

    GrabbedRigidbody grb = obj.AddComponent<GrabbedRigidbody>();
    grabbedRBfunc = grb;

    go = new GameObject();
    go.transform.parent = hand.transform;
    go.transform.localPosition = Enscale(palmOffset, go.transform.localScale);
    if (whichHand == WhichHands.Right)
        go.transform.localRotation = Quaternion.Euler(20,270,0); 
        go.transform.localRotation = Quaternion.Euler(-20,270,180);

    grb.Kinematize(hand.transform, whichHand == WhichHands.Right, hand.transform.position + palmOffsetWorld, go);


}

private Vector3 Enscale(Vector3 position, Vector3 scale) {
    return new Vector3(
        position.x * scale.x,
        position.y * scale.y,
        position.z * scale.z);
}

public abstract class Digit {
    public abstract void Init(GameObject hand, Vector3 handRightAxis, WhichHands whichHand);
    public abstract void Update(float inputValue);
}

[System.Serializable]
public class Finger : Digit {
    public Transform transform;
    public float input;
    private float val;
    private Vector3 axis;
    private float grabAmount = 0;
    private int nPhalanges;
    private Phalanx[] phalanges;

    public override void Init(GameObject hand, Vector3 axis_in, WhichHands whichHand) {
        if (transform != null) {
            axis = axis_in;

            phalanges = new Phalanx[3];
            phalanges[0] = new Phalanx(transform);
            if (phalanges[0].transform.childCount == 1) {
                phalanges[1] = new Phalanx(phalanges[0].transform.GetChild(0).transform);
                if (phalanges[1].transform.childCount == 1) {
                    phalanges[2] = new Phalanx(phalanges[1].transform.GetChild(0).transform);
                    nPhalanges = 3;
                } else {
                    phalanges[2] = null;
                    nPhalanges = 2;
                }
            } else {
                phalanges[1] = null;
                nPhalanges = 1;
            }
        }
    }

    private float grabSpeed = 0.1f;
    public override void Update(float inputValue) {
        if (transform != null) {
            input = inputValue;
            if (grabAmount > 0)
                val = grabAmount;
            else {
                float d = input - val;
                if (d > grabSpeed)
                    val += grabSpeed;
                else if (d < -grabSpeed)
                    val -= grabSpeed;
                else
                    val += d;
            }
            Bend();

            if (grabAmount > 0) {
                if (input < grabAmount) {

                    grabAmount = 0f;
                }
            }
        }
    }

    private void Bend() {
        switch (nPhalanges) {
        case 3:
            phalanges[0].Bend(val * 45, axis);
            phalanges[1].Bend(val * 90, axis);
            phalanges[2].Bend(val * 90, axis);
            break;
        case 2:
            phalanges[0].Bend(val * 90, axis);
            phalanges[1].Bend(val * 90, axis);
            break;
        case 1:
            phalanges[0].Bend(val * 135, axis);
            break;
        }
    }

    public bool hasGrabbed() {
        return (grabAmount > 0);
    }

    public void Grab() {
        grabAmount = val;
    }
}

[System.Serializable]
public class Thumb : Digit {
    public Transform transform;
    public float input;
    private float val, grabAmount = 0;
    private Vector3 axis1, axis2;
    private Quaternion startRotation;

    public override void Init(GameObject hand, Vector3 handRightAxis, WhichHands whichHand) {
        if (transform != null) {
            axis1 = transform.InverseTransformDirection(hand.transform.up);
            if (whichHand == WhichHands.Left)
                axis2 = transform.InverseTransformDirection(-hand.transform.forward);
            else
                axis2 = transform.InverseTransformDirection(hand.transform.forward);
            startRotation = transform.localRotation;
            startRotation *= Quaternion.AngleAxis(45, -axis1);
        }
    }

    private float grabSpeed = 0.1f;
    public override void Update(float inputValue) {
        if (transform != null) {
            input = inputValue;
            if (grabAmount > 0)
                val = grabAmount;
            else {
                float d = input - val;
                if (d > grabSpeed)
                    val += grabSpeed;
                else if (d < -grabSpeed)
                    val -= grabSpeed;
                else
                    val += d;
            }
            transform.localRotation = startRotation * Quaternion.AngleAxis(val * 45, axis1);
            transform.localRotation *= Quaternion.AngleAxis(val * 30, axis2);
        }
    }
}

[System.Serializable]
public class Phalanx {
    public Transform transform;
    public Quaternion startRotation;

    public Phalanx(Transform newTransform) {
        transform = newTransform;
        startRotation = transform.localRotation;
    }

    public void Bend(float bendFactor, Vector3 axis) {
        transform.localRotation = startRotation * Quaternion.AngleAxis(bendFactor, axis);
    }
}

}