๐Ÿ–๏ธHand

The core component of Auto Hand. This will manage Grabbing, Highlighting, Posing, and Movement. Requires a rigidbody. This component should be added to the root of your hand model, which should contain the rigged skeleton and the skinned mesh rendered underneath it

Core Settings

The hand requires finger components and a palm transform to generate poses

Finger

Each knuckle on the skeleton should have a finger component. The finger requires a transform that represents the finger tip and tip radius (which will act as a bumper for automatic grabbing)

The fingers must be connected before the open/closed poses can be saved

โ˜๏ธpageFinger Component

Palm Transform

The palm transform represents the point and forward direction of the grab. This will affect where the automatic grab will be positioned in the hand and where the cone that looks for grab targets is projected from.

This should be an empty transform placed at the center of the palm, with the LOCAL forward rotation (blue arrow) facing away from the hand

Movement

The hand will follow the given transform and match it's position/rotation using rigidbody forces

You can disable movement by disabling this Enable Movement toggle, or setting the rigidbody to be kinematic

The hand will teleport to the follow position if it's distance from the follow target is greater than the max follow distance. If the hand is holding a grabbable during teleport it will release or bring the held object based on the grabbable's "parent on grab" value

Follow represents the transform that the hand will use physics movement to try and match

  • (Recommend making the follow an empty transform under the controller, which can be used to offset the hands position/rotation)

Max Follow Distance will force the hand to teleport to the follow transform if greater than this distance

Throw Power multiplies the velocity of the grabbable on release by this value

Enable Interpolation applies position interpolation to the hands to make them look smoother when the FPS is higher than the fixed timestep

Posing

Disable this module when doing custom animations. The posing module will update the fingers, create finger sway, and look for custom pose areas. The Grab/AutoPose functions will still perform poses.

Sway Strength will be how much the fingers sway when the hands moves, 0 to disable

Grip Offset will offset the bend of every finger. 0.14 is slight bend 1 is full bend

Automatic posing is default when grabbing a Grabbable without any custom pose components

Learn more: โœCustom Poses

Highlighting

The highlighting module will look for grabbables to highlight. This is a passive system should be disabled for optimization purposes when not being used. If Highlight layers are left on nothing, it will default to grabbable, so make sure to disable the Enable Highlight toggle instead.

Highlighting events are triggered when an object is being targeted for grabbing

Highlight Layers represents which layers the highlight module will search for, (will default to grabbable if left blank to disable highlighting uncheck Enable Highlight)

Default Highlight material will be applied to all grabbables without a highlight material

  • Highlight Material works by making a copy of the target grabbable's mesh, applying the highlighted material, and scaling it up slightly

Advanced Options

  • Grab Type decides whether the hand grabs objects, objects move to hands, or are instant grab

  • Grab Curve represents the animation over the grab time of the grab

    • (x = grab time from 0-1, y = grab pose from 0-1)

  • Gentle Grab Speed multiplies the controller movement required to return the object if the grabbable's gentle grab value is enabled

  • Pose index must match the pose index of pose components to work (added for supporting more than one hand model per game)

Events

While the Auto Hand includes internal C# Events, public Unity Events can be found through the Hand Public Events component

  • On Before Grab is called after a grab is confirmed possible, before the grab has started

  • On Grab is called when the hand touches the grabbable, after the grab connection is made

  • On Release is called when the hand releases the grabbable

  • On Force Release is called when the force release function is called forcing the object to be โ€œdroppedโ€ instead of properly released

  • On Squeeze called on when the squeeze button is trigger while holding a grabbable. Squeeze button is determined by the Hand Controller Link settings (attached to โ€œInputโ€ gameobject under hands in demo)

Controller Input

Manages the controller input for hand grab/release triggers and the squeeze/unsqueeze events

Haptic Collisions

An optional component that can be added to the Hand object is the Hand Collision Haptics this component will cause controller vibrations (if supported by input system) when the hands collide with objects on the collision triggers mask.

Grab Lock

You can add the Grab Lock component onto a Grabbable object to prevent it from being released via the usual Hand.Release() method. Instead you will have to call the Hand.ForceRelease() or Hand.ReleaseGrabLock() method to drop an grabbable with this component

Distance Grabbing

๐ŸงฒpageDistance Grabbing

Hand Projection

๐Ÿ”ฆpageHand Projector

Programming Info

Auto Hand hands have four essential functions, Grab(), Release(), Squeeze(), and Unsqueeze()

Grabbing

Grabbing is best done with the default Grab() function, but grabbing only what is in front of the hand does not fit every use case. While the Grab() functions are most consistent, if you do not have a meaning of getting a proper raycasthit you can use the TryGrab() function instead

//Will grab whatever is in front of and closest to the hands palm
hand.Grab()

//Will grab the grabbable target given a raycast hit
hand.Grab(RaycastHit hit, Grabbable target)

//Will try to automatically create a useable raycast hit to do a grab with just a target
hand.TryGrab(Grabbable target)

//(Good for syncing grabs over a network) 
//Will forcably create a grab connection using the given values without creating an Auto Pose
hand.CreateGrabConnection(Grabbable grab, Vector3 handPos, Quaternion handRot, Vector3 grabPos, Quaternion grabRot, bool executeGrabEvents = false)

Releasing

The Release() function will release whatever the hand is currently holding and apply the hands velocity and throw power to the grabbable. ForceRelease() will release the grabbable without applying throw force. Both will call the OnReleaseEvent

//Will release the hand and add hand throw velocity
hand.Release();

//Will release the hands object without applying throw (like it was dropped)
hand.ForceRelease();

Squeezing

The Squeeze() function is used to call an additional event on the grabbable and hand through controller input while held

//Will trigger squeeze event on the hand and held grabbable
hand.Squeeze();

//Will trigger unsqueeze event on the hand and held grabbable
hand.Unsqueeze();

Haptics

Auto Hand haptics supported for XR, SteamVR, and OVR if supported by your device for that system (Haptics not currently supported through OpenXR)

//Will play haptic on the hand if supported by input system and device
hand.PlayHapticVibration()
hand.PlayHapticVibration(float duration)
hand.PlayHapticVibration(float duration, float amp)

Auto Posing Function

Advanced users might want to use just the Auto Pose generation in their system. In order to do so you must get a raycast hit point on the surface of your grab target

//This will generate and set the hand model as a grab pose based on a raycast hit and grabbabe
//THIS WILL NOT CREATE GRAB CONNECTIONS OR CALL GRAB EVENTS
hand.AutoPose(RaycastHit hit, Grabbable grabbable)

Set Location

You can use the hand.SetLocation(Vector3 position, Quaternion rotation) to set the hand position/rotation. If the hand is holding a grabbable during this function call it will release or bring the held object based on the whether or not the grabbable's "parent on grab" is true

//Will set the hands position/rotatation
hand.SetLocation(Vector3 position, Quaternion rotation) 

For more advanced information on internal settings and custom layer options, see

Programming Events

using UnityEngine;
using Autohand;

public class HandEventTemplate : MonoBehaviour{
    public Hand hand;

    void OnEnable() {
        hand.OnBeforeGrabbed += OnBeforeGrabbed;
        hand.OnGrabbed += OnGrabbed;
        hand.OnBeforeReleased += OnBeforeReleased;
        hand.OnReleased += OnReleased;
        hand.OnForcedRelease += OnForcedRelease;
        hand.OnGrabJointBreak += OnGrabJointBreak;

        hand.OnHandCollisionStart += OnHandCollisionStart;
        hand.OnHandCollisionStop += OnHandCollisionStop;
        hand.OnHandTriggerStart += OnHandTriggerStart;
        hand.OnHandTriggerStop += OnHandTriggerStop;

        hand.OnHighlight += OnHighlight;
        hand.OnStopHighlight += OnStopHighlight;

        hand.OnSqueezed += OnSqueezed;
        hand.OnUnsqueezed += OnUnsqueezed;

        hand.OnTriggerGrab += OnTriggerGrab;
        hand.OnTriggerRelease += OnTriggerRelease;
    }

    void OnDisable() {
        hand.OnBeforeGrabbed -= OnBeforeGrabbed;
        hand.OnGrabbed -= OnGrabbed;
        hand.OnBeforeReleased -= OnBeforeReleased;
        hand.OnReleased -= OnReleased;
        hand.OnForcedRelease -= OnForcedRelease;
        hand.OnGrabJointBreak -= OnGrabJointBreak;

        hand.OnHighlight -= OnHighlight;
        hand.OnStopHighlight -= OnStopHighlight;

        hand.OnSqueezed -= OnSqueezed;
        hand.OnUnsqueezed -= OnUnsqueezed;

        hand.OnTriggerGrab -= OnTriggerGrab;
        hand.OnTriggerRelease -= OnTriggerRelease;

        hand.OnHandCollisionStart -= OnHandCollisionStart;
        hand.OnHandCollisionStop -= OnHandCollisionStop;
        hand.OnHandTriggerStart -= OnHandTriggerStart;
        hand.OnHandTriggerStop -= OnHandTriggerStop;
    }

    void OnBeforeGrabbed(Hand hand, Grabbable grab) {
        //Called when an object is grabbed before anything else
    }

    void OnGrabbed(Hand hand, Grabbable grab) {
        //Called when an object is grabbed
    }

    void OnBeforeReleased(Hand hand, Grabbable grab) {
        //Called when a held object is released before anything else
    }

    void OnReleased(Hand hand, Grabbable grab) {
        //Called when a held object is released
    }

    void OnForcedRelease(Hand hand, Grabbable grab) {
        //Called when the force release functions is called

    }

    void OnGrabJointBreak(Hand hand, Grabbable grab) {
        //Called when the joint between the hand the grabbable breaks
    }

    void OnHighlight(Hand hand, Grabbable grab) {
        //Called when the hand grab targets a new object
    }
    
    void OnStopHighlight(Hand hand, Grabbable grab) {
        //Called when the hand grab stops targeting an object
    }

    void OnSqueezed(Hand hand, Grabbable grab) {
        //Called when the "Squeeze" event is called, this event is tied to a secondary controller input through the HandControllerLink component on the hand
    }
    void OnUnsqueezed(Hand hand, Grabbable grab) {
        //Called when the "Unsqueeze" event is called, this event is tied to a secondary controller input through the HandControllerLink component on the hand
    }

    void OnTriggerGrab(Hand hand, Grabbable grab) {
        //Called when the "Grab" event is called, regardless of whether something is being grabbed or not
    }
    void OnTriggerRelease(Hand hand, Grabbable grab) {
        //Called when the "Release" event is called, regardless of whether something is being held or released
    }

    void OnHandCollisionStart(Hand hand, GameObject other) {
        //Called when the hand hits an object for the first time and isn't already colliding
    }

    void OnHandCollisionStop(Hand hand, GameObject other) {
        //Called all the hand has zero collisions on the object

    }

    void OnHandTriggerStart(Hand hand, GameObject other) {
        //Called when the hand triggers an object for the first time and isn't already triggering
    }

    void OnHandTriggerStop(Hand hand, GameObject other) {
        //Called when the hand has zero colliders overlapping this trigger
    }

}

Last updated