Microtube Docs
Developers / Unity / SDK architecture & API

SDK Architecture & API

How the HEXR Unity SDK is put together, how the glove connects, how interactions become haptics, and how to drive the glove from your own code.

SDK version

This page describes com.microtube.hexr version 0.9.4, released 11 October 2026. See the changelog for earlier releases.

Package structure

The package is a stack. Your scene talks to the top; the glove sits at the bottom. The two backend layers only compile when their XR SDK is installed, and the core never depends on them.

AssemblyNamespaceHoldsCompiles when
HaptGlove.RuntimeHaptGloveHaptGloveHandler, Bluetooth transports, Haptics command buildersAlways
HexR.RuntimeHexRManager, hand tracking, Pressure Controllers, touch points, scene components, HexR menuAlways
HexR.Runtime.MetaOVRHexR.MetaOVRMeta grab and poke detection, interactable events, passthroughMeta Interaction SDK installed
HexR.Runtime.OpenXRHexR.OpenXRXR Interaction Toolkit integration (OpenXR headsets, including PICO)XR Interaction Toolkit installed
HexR.EditorHexRHexR menu, Auto Setup, validator, HexR Tools windowEditor only

Backends register themselves with the core when they load. The collider visualizer, HexRUsable and the HexR menu stay in the global namespace so older scenes keep working.

The HEXR scene

HexR → Create HexR Rig adds the first two. Your XR SDK provides the third.

ObjectComponentsRole
HexR MainHexRManagerOwns both gloves, runs connections, re-attaches the hands after a scene change. Reach it as HexRManager.Instance
Left / Right Hand PhysicsHaptGloveHandler, HexRTrackedHand, FingerUseTrackingOne per hand: the Bluetooth link, which tracked hand it follows, how bent each finger is
HexR Floating MenuHexRFloatingMenuThe HexR menu, in the headset: connect gloves, show touch points, watch each finger’s haptics, switch scenes and demos. Pressed with a fingertip
Left / Right Pressure ControllerPressureTrackerMainThe haptics controller for that hand
Every scene needs one active pair of Pressure Controllers

The touch points find them by name when the scene starts. A hand without one produces no haptics. HexR → Add Pressure Controller adds them.

The tracked hand

HexRTrackedHand.handRoot points at your SDK’s hand. HEXR finds the joints by name:

XR SDKHand rootJoints
Meta Interaction SDKOpenXRLeftHand / OpenXRRightHandXRHand_IndexTip, XRHand_Palm, …
XR Interaction Toolkit + XR HandsL_Wrist / R_Wrist under Left / Right Hand Interaction VisualL_IndexTip, L_Palm, …

Each touch point is a small trigger collider, a kinematic Rigidbody (Unity needs one for trigger events) and a HapticFingerTrigger that says which hand and finger it is. HEXR has no hand of its own: since 0.9 the touch points sit on the tracked hand on every backend. An older project with a “ghost” hand can remove it with HexR → Migration → Remove Ghost Hand.

Connecting the glove

Your app opens the Bluetooth connection itself. No pairing in system settings, no companion app. Each glove has its own HaptGloveHandler.

Where your app runsBluetooth
Android headsets — Meta Quest, PICOSupported; the rig’s default
Windows — Unity Editor and 64-bit buildsSupported. In a build, set Build Platform on each HaptGloveHandler to Window. In the Editor, connect from the HexR Haptics Tester, which does this for Play mode
macOS, iOS, Linux, HoloLens (UWP)Not supported by the package. A macOS Bluetooth library ships inside it, but nothing calls it yet

The whole list, headsets included, is in Platform & headset support.

Events

Public UnityAction fields on HaptGloveHandler. Subscribe with += and unsubscribe with -=. Never assign with =: that removes the handlers HexRManager relies on. They are not UnityEvents, so they do not show in the Inspector.

EventWhen
onBluetoothConnected(HandType)The glove connected
onBluetoothConnectionFailed(HandType)An attempt failed
onBluetoothDisconnected(HandType)The link closed: the glove dropped out, you disconnected it, or the app is shutting down
onPumpAction(HandType, bool)The air supply started or stopped
onBatteryStateChange(BatteryState)Full, Medium or Low
onDeviceFound(id, name)A scan found a device
HexRManager.ConnectAttemptEndedStatic. A connect attempt ended without a connection: the permission was refused, or an attempt failed, including one that will be retried. Not raised on success; use onBluetoothConnected for that

How haptics fire

TriggerUse it forExample
XR interaction eventsFeeling an object while it is grabbed or hoveredHexRInteractableHaptics
Physics contactFeeling a surface, a liquid, a heartbeatSpecialHaptics
Your codeGame events, sequences, testsPressureTrackerMain

Latency

The time from an event in your app to a sensation is three delays added together. They are listed separately because only the last one is set by the glove; the other two depend on your setup.

StageWhat happensHow long
1 · Your app to the radioOn Quest and PICO builds, Quest BLE Buffering is on in both packaged rigs: commands are collected and sent as one Bluetooth write at most every 100 ms, checked on Unity’s fixed update. On Windows, and in Python, each command is written as soon as you send itUp to about 100 ms on Quest and PICO with buffering on
2 · BluetoothThe glove asks for a 7.5 ms connection interval; the phone, headset or PC chooses the interval it actually uses. Android and Python write with a response from the gloveSet by the host; not measured
3 · The gloveThe pump starts driving within one 20 ms control cycle of a pressure command arriving, then ramps to the target. At the fastest speed (1) the ramp takes about 60 ms per 10 kPa: roughly 90 ms to the lightest intensity, 300 ms to the firmest, and ten times longer at speed 0.1. Vibration at 5 Hz and above starts on the next pass of the control loop. A release stops the pump at onceFrom the firmware source; not a bench measurement

End-to-end latency — from your event to the moment the user feels it — has not been measured for the current glove, and no figure for it is published here. If your application depends on it, measure it on your own setup.

Quest BLE Buffering is a trade

Buffering sends fewer, larger Bluetooth writes, at the cost of waiting up to 100 ms. Turning it off (the Quest BLE Buffering setting on HexRManager) writes every command immediately, but commands sent back to back can then be dropped on Android. It has only been tested on Quest; if a PICO build connects but feels laggy or silent, try it both ways.

The hand-near check

A Pressure Controller sends most haptics only while IsHandNear() is true. Any one of these makes it true:

SignalSet by
Grabbing, or hovering to grabYour SDK’s grab interactor — Meta’s HandGrabInteractor, or XRI’s XRDirectInteractor or (from 0.9.4) NearFarInteractor. Wired for you by Auto Setup and on every scene load. For a Near-Far Interactor only a near grab counts, and its hover only with far casting off: an object grabbed along the ray from across the room does not press the glove
Poking, or about toYour SDK’s poke interactor — Meta’s PokeInteractor or XRI’s XRPokeInteractor, wired the same way
A fingertip inside a ProximityCheck volumeA ProximityCheck you add to an object your interactors do not cover. It stays set for 0.5 s after the fingertip leaves, its clearDelay default

The three results are public fields on each PressureTrackerMain: HandGrabbing, PokeHovering and CollisionNearHand. The check itself, IsHandNear(), is private. It is per hand: one signal anywhere opens it for every gated call on that hand.

CheckedNot checked
Single…Haptic, TriggerAll…, TriggerCustom…, TriggerPinchPressureHapticFingerTrigger.TriggerFixPressure, every SpecialHaptics effect, CustomSingleHaptics / CustomSingleVibrations with ByPassHandCheck set to true, RemoveAllHaptics, RemoveAllVibrations and the Remove…Haptics calls

Releases are checked too when they go through a checked call: RemovePinchPressure(), and CustomSingleHaptics with false as the last argument, are dropped if the hand has already left. Release with RemoveAllHaptics(), a Remove…Haptics() call, or true as the last argument.

If your call does nothing, select the Pressure Controller, switch the Inspector to Debug and watch its three flags, or pass true as ByPassHandCheck while testing.

Channels and parameters

Six channels: Haptics.Finger.Thumb, Index, Middle, Ring, Pinky, Palm. Each plays one mode at a time. Values outside a range are clamped.

ModeFeels likeParameters
PressureA steady pressintensity 0.1–1 (about 15–50 kPa); speed 0.1–1, how fast it ramps
VibrationPressure pulsing on and offfrequency 0.1–40 Hz; intensity 0.1–1. Below 5 Hz it sets pulse pressure, from 5 Hz pulse length
Slow pulseA shaped, slow rhythmfrequency 0.1–2 Hz; intensity; peakRatio 0.2–0.8; speed; endIntensity (below 0.1 releases)
Counted pulsesA set number of pulsesfrequency; intensity; pulseCount 1–1000

The scene components show their strength on a 10–60 scale — 10 is barely there, 60 is firm — and convert it to the 0.1–1 intensity above. Use PressureTrackerMain.StrengthToIntensity(strength) to do the same in your own code.

Releasing the glove

The glove keeps its last command until it is told otherwise; nothing on it lets go by itself. What the package does about that:

WhenWhat happens
A component is disabled or destroyedHexRInteractableHaptics, HexRPhysicalButton, HexRGrabbable and SpecialHaptics release the channels they pressed. The last two from 0.9.4; a SpecialHaptics zone releases only its own channels, not another component’s
The app quits, including stopping Play mode in the EditorEvery channel on both gloves is released, then the link is closed. From 0.9.4
The app pauses: the headset is taken off, or the app goes to the backgroundEvery channel is released, while HaptGloveHandler.releaseWhenPaused is on (the default). Effects do not come back by themselves on resume; the next change re-applies them. From 0.9.4
You disconnect: Disconnect(hand), or the menu’s toggleThe glove is released first, then the link is closed. From 0.9.4
The app crashes or is force-closedNothing can be sent. The glove keeps pressing
The Bluetooth link dropsNothing can be sent. The glove keeps pressing, and the handler reconnects on Android without releasing. See Release on reconnect
If a glove is left pressing

Switch the arm module off. A release on link loss would have to come from the glove’s firmware, which does not do that today. In your own code, release what you apply — in OnDisable too — or call ReleaseAllChannels() on the glove handler.

Scene components

Most projects never call the API. These components fire haptics on their own.

ComponentUse it forKey fields
HexRInteractableHaptics — start hereFeel your SDK’s own interactable (XRI or Meta) while grabbed or hovered. The backend is picked automatically. Releases its channels when disabledfireOn Select / Hover / SelectAndHover; finger toggles; strength 10–60; followGrip, which scales it between minStrength and strength by how far the fingers have closed (both fixed in 0.9.4); backend
SpecialHapticsA trigger collider that plays a preset effect when touched. Ignores the hand-near checkRPressureTracker and LPressureTracker (required: Auto Find Hand Physics fills them), TypeOfHaptics (table below), HapticPressure, VibrationsFrequencyValue, InTimer / OutTimer
ProximityCheckTell the Pressure Controller a hand is near an object that is not an SDK interactableAuto Set Up button wires both Pressure Controllers
HexRPhysicalButtonA button pressed by a real fingertip, no SDK needed. The HexR menu is built from itonPressed; accepted fingers (index by default)
HexRUsableTriggers, handles, grips: raises events when chosen fingers curl. Both backends from 0.9.4; OpenXR only beforeUseThreshold; WhenUseTriggerEvents / WhenStopUsingTriggerEvents
HapticFingerTriggerThe touch point itself. Read it in your own OnTriggerEnter to learn which hand and finger touchedhandType, fingertype; TriggerFixPressure, TriggerVibrationPressure, RemoveHaptics
HexRGrabbableHEXR's own grab, picked up by the glove hands with no interaction SDK. Sends straight to the glove, without the hand-near check. Before 0.9.4 it threw on start without a parent object and its haptics threw on grabPinchGrab / PalmGrab; HapticStrength 10–60; needs a Rigidbody and a trigger collider
SpecialHaptics effectFeels like
CustomHapticsConstant pressure while touched
CustomVibrationsVibration at a set frequency and strength
FountainEffectRunning water
RainDropEffectRaindrops on the palm
HeartBeatEffectA beating heart, regular or irregular
HandSqueezeEffectFires OnSqueezeEventTrigger when the hand closes on the zone. Needs FingerUseTracking on the rig’s hands

Which component do I need?

You want…UseGood to know
To feel an object while your XR SDK grabs, pokes or hovers itHexRInteractableHaptics beside the SDK’s interactableNeeds an XRI or Meta interactable on the object or a child, or it does nothing. Leave Backend on Auto
A surface or volume that feels like something — water, rain, a heartbeat, a buzzSpecialHaptics on a trigger colliderFires on contact alone and ignores the hand-near check, so it needs no ProximityCheck
A button pressed by a fingertip, without an SDKHexRPhysicalButtonNeeds a trigger collider
Something to happen when the fingers curlHexRUsableWorks on Meta and OpenXR from 0.9.4. Earlier releases told the hands apart by the L_ / R_ joint names, which Meta’s skeleton does not use
Gated haptics on an object your rig’s grab and poke interactors do not coverAdd ProximityCheckPress its Auto Set Up. On its own it fires nothing
Exact control from your own codePressureTrackerMain methodsRelease what you apply — see Triggering feedback

Using components together

CombinationResult
HexRInteractableHaptics + ProximityCheckWorks. Only needed when your rig’s interactors do not feed the hand-near check, such as hover-triggered haptics on a Near-Far rig with far casting on, or any OpenXR rig before 0.9.4; otherwise redundant
A SpecialHaptics zone on a grabbable objectWorks. The PICO tutorial’s heart beats this way
SpecialHaptics + ProximityCheckWorks but not needed. The zone ignores the check, and while a hand is inside, the ProximityCheck opens that hand’s check for every other gated call too
HexRInteractableHaptics + UnityEvents on the same interactable calling a Pressure ControllerAvoid. Both drive the same channels and whichever ran last wins; the Inspector warns about it
HexRInteractableHaptics + HexRGrabbableAvoid. Two separate grab systems move the object and both send haptics

The hand-near check is per hand, not per object: a grab, hover or ProximityCheck anywhere opens it for every gated call on that hand.

C# API

Call these when you want haptics driven by your own logic.

PressureTrackerMain — on each Pressure Controller

MethodDoes
CustomSingleHaptics(finger, States, TargetPressure, Speed, ByPassHandCheck)Pressure on one channel. States true applies, false releases; TargetPressure and Speed 0.1–1. Named arguments must use these exact names
CustomSingleVibrations(finger, States, TargetPressure, frequency, ByPassHandCheck)Vibration on one channel; frequency 0.1–40 Hz
SingleThumbHaptic(float) … SinglePalmHaptic(float)Pressure 0.1–1 on one channel. One float, so they wire to a UnityEvent
RemoveThumbHaptics() … RemovePalmHaptics()Release one channel
TriggerAllHapticsIncrease(float) / TriggerAllVibrations(frequency)Every channel at once
TriggerCustomHapticsIncrease(bool[6], pressure, speed) / TriggerCustomlVibrations(bool[6], intensity, frequency)A chosen set of channels, in Thumb…Palm order
TriggerPinchPressure(float) / RemovePinchPressure()Thumb-and-index pinch. The release is checked, so pair it with RemoveAllHaptics() if the hand may have left
RemoveAllHaptics() / RemoveAllVibrations()Release everything. Never blocked by the hand-near check; send both to be sure every channel is off
HandGrabbing, PokeHovering, CollisionNearHandThe three inputs to the hand-near check. Read them; Auto Setup and the scene components set them
StrengthToIntensity(strength)Static. Converts the components’ 10–60 strength scale to the 0.1–1 intensity these methods take. From 0.9.4
TrackedHandRootThe tracked hand this side of the rig follows, or null before one is found. From 0.9.4

HexRManager — HexRManager.Instance

MemberDoes
Connect(hand)Connect that glove, with the permission request and the one-hand-at-a-time rule. Does nothing if it is already connected or connecting, and needs no HexR menu. hand is HaptGloveHandler.HandType.Left or Right. From 0.9.4
Disconnect(hand)Release that glove, then disconnect it. Does nothing if it is not connected. From 0.9.4
IsConnected(hand), IsConnecting(hand)Connected right now; a connect under way, including waiting for permission or a retry. From 0.9.4
ConnectLeftBT() / ConnectRightBT()What the menu’s buttons call. A toggle: on a connected glove it disconnects, and during a retry it cancels. From code, prefer Connect(hand). Before 0.9.4 these threw without the HexR menu in the scene
leftHand / rightHandEach glove’s HaptGloveHandler
XRFrameworkOpenXR or MetaOVR
RebindHandsToCurrentScene()Re-attach the touch points to this scene’s hands. Runs by itself on every scene load
Collider settingsSize and placement of the touch points Auto Setup adds, per skeleton
ConnectAttemptEndedStatic event: a connect attempt ended without a connection. See Events

HaptGloveHandler — one per glove, namespace HaptGlove

MemberDoes
whichHandLeft or Right
BTConnection()Connect, or disconnect if connected. Prefer the manager’s Connect(hand), which adds permissions and the one-at-a-time rule
IsConnectingA connect is under way, including the wait between retries. From 0.9.4
ReleaseAllChannels(), ReleaseChannels(params Haptics.Finger[])Switch channels off, vibration and pressure alike, in one write. Nothing is sent while the glove is not connected. From 0.9.4
releaseWhenPausedRelease every channel when the app pauses. On by default. From 0.9.4
bleConnectedConnected right now?
UseCustomDeviceName, OptionalCustomDeviceNameLook for a glove by a name you choose
RememberDevice(id), ForgetDevice(), ConnectToDevice(id)Which glove it goes straight to
hapticsBuilds commands: HEXRPressure, HEXRVibration, HEXRPulse. GetChannelState(finger) returns what the last command set on a channel, as a ChannelState (HapticMode, intensity, frequency)
BTSend(byte[])Send a command straight to the glove. Skips the hand-near check
GetBatteryLevel(), GetAirPressure()Latest battery level and pressure readings

HexRTrackedHand and FingerUseTracking — on each hand

MemberDoes
HexRTrackedHand.handType, handRootWhich hand, and the tracked hand it follows
ResolveRawFingerJoint(finger), ResolveRawPalmJoint()The tip or palm joint, on either skeleton
FingerUseTracking.ThumbUse … LittleUse0 = fully curled, 1 = fully extended. Self-calibrating: settles once the hand has opened and closed
FingerUseTracking.isHandOpen()All fingers extended?

Scene changes and editor tools

Your SDK’s hands die with their scene; the rig lives on. So after every scene load the manager re-attaches:

Then the log says [HexR] Rebound Left hand … 6 haptic trigger(s): five fingertips and the palm.

Auto Setup does the same in the Editor so it is saved with the scene. It only adds what is missing and never moves a collider you tuned. Run it from Create HexR Rig, HexR → Troubleshoot → Re-run Auto Setup, or the manager’s Auto Set Up HexR button. Validate Scene Setup then reports anything still unwired.

MenuDoes
HexR → HexR ToolsThe tools window, three tabs: HexR Haptics Tester (connect a glove in Play mode, fire any channel, watch live pressure, All OFF), HexR Setup (the validator as a checklist, with Fix all), Project Setup (pick OpenXR, Meta OVR or PICO; installs its packages)
HexR → Create Demo SceneRig, Pressure Controllers, a grabbable object and a haptic zone
HexR → Create HexR RigThe rig and Pressure Controllers for your backend, then Auto Setup
HexR → Add Pressure ControllerThe pair of Pressure Controllers
HexR → Add HexR MenuThe HexR menu in your own scene
HexR → TroubleshootRe-run Auto Setup, Validate Scene Setup
HexR → MigrationOne-off upgrades, such as Remove Ghost Hand
HexR menu → Show CollidersDraws every touch point on the tracked hands
HexR menu → HAPTICSThe value last sent to each finger and the palm of each glove, after it was clamped to the valid range: lit while on, dimmed after. Turn it off with showHapticsReadout

Type index

Every public type in com.microtube.hexr, for looking a name up. Where a section above covers it, the link goes there.

Components

TypeWhat it is
HexRManagerThe rig: both gloves, connections, re-attaching the hands. Members
HaptGloveHandlerOne glove’s Bluetooth link and command sender. Members
PressureTrackerMainA Pressure Controller: every haptic for one hand goes through it. Methods
HexRTrackedHand, FingerUseTrackingWhich tracked hand a glove follows, and how bent each finger is. Members
HapticFingerTriggerThe touch point on each fingertip and the palm. Scene components
HexRInteractableHapticsHaptics on your SDK’s own interactable. Scene components
HexRGrabbableHEXR’s own grab, by the glove hands with no interaction SDK. Scene components
SpecialHaptics, ProximityCheck, HexRPhysicalButton, HexRUsablePreset effects, the hand-near volume, fingertip buttons, curl-to-use. Scene components
HexRFloatingMenuThe in-headset panel. The HEXR scene
HaptGloveCollidersVisualizerDraws the touch points; what the menu’s Show Colliders uses. SetVisible(bool), IsShowing
HaptGloveUIOn HexR Main: passes Connect presses on to the manager’s ConnectLeftBT() / ConnectRightBT(). Kept for older panels; it updates no text itself
SceneLoaderScene transitions for the app. Sits on the same persistent object as HexRManager
HexRGripByHandOpenXR: gives a stock XRGrabInteractable a grip per hand, and a pinch or fist hold, without replacing it. GripMode picks the hold
OpenXRHandNearSource, MetaOVRHandNearSourceFeed the hand-near check from the grab and poke interactors. Auto Setup adds them
OpenXRBackendSetup, MetaOVRBackendSetupWire those sources onto the Pressure Controllers, in the Editor and at run time. Nothing to add yourself
MetaOVRPassthrough, IHexRPassthroughPassthrough on Meta, and the interface the menu uses to refresh any backend’s passthrough after a scene load

Enums and values

TypeValues and where it is used
HapticsCommand builders, on HaptGloveHandler.haptics. Channels and parameters
Haptics.FingerThumb, Index, Middle, Ring, Pinky, Palm
Haptics.HapticMode, Haptics.ChannelStateWhat the last command set on a channel: Off, Pressure, Vibration or Pulse, with intensity and frequency. From GetChannelState(finger)
HandTypeLeft / Right, on HaptGloveHandler and on HapticFingerTrigger
FingerTypeWhich finger a HapticFingerTrigger is, in fingertype
BatteryStateFull, Medium, Low. Events
TargetPlatformA glove handler’s Build Platform: Android or Window (spelled without an s). Connecting the glove
FireOnHexRInteractableHaptics.fireOn: Select, Hover, SelectAndHover
HexRBackendChoiceWhich interaction SDK drives a component: Auto or a named backend
HexRHandSideWhich hand an interaction came from, as a backend reports it
HeartBeatSpecialHaptics heartbeat: Regular or Irregular
Options, OptionHexRGrabbable.Options PinchGrab / PalmGrab; HexRGrabbable.Option gravity On / Off; HexRManager.Options is XRFramework
FingertipCentersPer-finger touch point offsets in the manager’s collider settings

Backend plumbing, editor and internals

TypeWhat it is
IHexRInteractionBackend, IHexRInteractionBinding, IHexRInteractionSink, HexRInteractionBackends, HexRHandSideResolverHow an XR SDK plugs into HEXR. Only needed to add a backend of your own
HexRCompatStand-ins for Unity APIs renamed between 2022.3 and Unity 6. See Unity version support
HexRMenu, HexRAutoSetup, HexRSetupValidator, SetupCheck, HexRToolsWindowEditor: the HexR menu, Auto Setup, Validate Scene Setup and the HexR Tools window. Editor tools
HexRSettingEditorGUI, HexRInteractableHapticsEditor, HapticEffectControllerEditor, ProximityCheckEditor, FingerUseTrackingEditorSettingEditor: the Inspectors for HexRManager, HexRInteractableHaptics, SpecialHaptics, ProximityCheck and FingerUseTracking
BLE, BLEScan, BLEData, Characteristic, Service, DeviceUpdate, ErrorMessage, ScanStatus, Encode, Decode, FunIndex, AndroidUiThreadInternal: the Bluetooth layer under HaptGloveHandler. Not for direct use; go through the handler or a Pressure Controller

Python

Outside Unity, HaptGlovePython builds the same commands; you write them with bleak. It needs Python 3.8 to 3.13. Setup and a tested example are in the Python guide.

MethodDoes
hexr_pressure(finger, state, intensity, speed)Pressure on one channel. state True applies; False with intensity 0 releases
hexr_pressure_multiple(fingers, states, intensities, speeds)Pressure on several channels in one write; intensities and speeds 0.1–1. All states False and intensities 0 releases them
hexr_vibrations(finger, state, frequency, intensity, peakRatio, speed, endIntensity)The slow pulse, 0.1–2 Hz. hexr_vibrations_multiple takes lists
AddressDiscovery.py, CharacteristicDiscovery.py, ExampleHaptics.pyFind your glove, list what it exposes, run a ready example
Fingers are enum members

Use Haptics.Finger.Index, not "Index". A string raises AttributeError.

Copy-paste examples

Whole scripts for the jobs that come up first. Each one compiles against com.microtube.hexr 0.9.4. Feeling an object while it is grabbed needs no code at all: put HexRInteractableHaptics on it.

Connect both gloves from code

No HexR menu needed. Put it on any object in the scene. In the Editor, connect from the HexR Haptics Tester instead — see Connecting the glove.

csharp
using UnityEngine;
using HaptGlove;
using HexR;

// Connects both gloves when the scene starts -- no HexR menu needed --
// and logs each one as it comes up or drops.
public class ConnectGloves : MonoBehaviour
{
    void Start()
    {
        HexRManager rig = HexRManager.Instance;
        rig.leftHand.onBluetoothConnected += OnConnected;
        rig.rightHand.onBluetoothConnected += OnConnected;
        rig.leftHand.onBluetoothDisconnected += OnDisconnected;
        rig.rightHand.onBluetoothDisconnected += OnDisconnected;

        // Does nothing for a glove that is already connected or connecting.
        rig.Connect(HaptGloveHandler.HandType.Left);
        rig.Connect(HaptGloveHandler.HandType.Right);
    }

    void OnDestroy()
    {
        HexRManager rig = HexRManager.Instance;
        if (rig == null) return;
        rig.leftHand.onBluetoothConnected -= OnConnected;
        rig.rightHand.onBluetoothConnected -= OnConnected;
        rig.leftHand.onBluetoothDisconnected -= OnDisconnected;
        rig.rightHand.onBluetoothDisconnected -= OnDisconnected;
    }

    void OnConnected(HaptGloveHandler.HandType hand) { Debug.Log(hand + " glove connected"); }
    void OnDisconnected(HaptGloveHandler.HandType hand) { Debug.Log(hand + " glove disconnected"); }
}

Press a finger on your own event

Drag a Pressure Controller into Hand, then wire Press and Release to any UnityEvent.

csharp
using UnityEngine;
using HaptGlove;
using HexR;

// Wire Press() and Release() to any UnityEvent: a button, a trigger, an
// animation event. Strength is on the same 10-60 scale as the components'.
public class PressOnEvent : MonoBehaviour
{
    public PressureTrackerMain hand;                  // a Pressure Controller
    public Haptics.Finger finger = Haptics.Finger.Index;
    [Range(10f, 60f)] public float strength = 30f;

    bool pressing;

    public void Press()
    {
        float intensity = PressureTrackerMain.StrengthToIntensity(strength);
        // true skips the hand-near check: this press answers your event, not a touch.
        hand.CustomSingleHaptics(finger, true, intensity, 1f, true);
        pressing = true;
    }

    public void Release()
    {
        if (!pressing) return;
        hand.CustomSingleHaptics(finger, false, 0f, 1f, true);
        pressing = false;
    }

    // Disabled, or the scene changes, mid-press: let go as well.
    void OnDisable() { Release(); }
}

Press the finger that touches an object

On any object with a trigger collider. HapticFingerTrigger on the touch point says which hand and finger touched, so it needs no Pressure Controller of its own.

csharp
using System.Collections.Generic;
using UnityEngine;
using HexR;

// On a trigger collider: presses exactly the finger or palm that touches it,
// on the hand it belongs to, and releases it when it leaves.
[RequireComponent(typeof(Collider))]
public class PressWhereTouched : MonoBehaviour
{
    [Range(0.1f, 1f)] public float intensity = 0.5f;

    readonly HashSet<HapticFingerTrigger> touching = new HashSet<HapticFingerTrigger>();

    void OnTriggerEnter(Collider other)
    {
        if (!other.TryGetComponent(out HapticFingerTrigger touch)) return;
        touch.TriggerFixPressure(intensity);   // 0.1-1, skips the hand-near check
        touching.Add(touch);
    }

    void OnTriggerExit(Collider other)
    {
        if (!other.TryGetComponent(out HapticFingerTrigger touch)) return;
        touch.RemoveHaptics();
        touching.Remove(touch);
    }

    // Disabled while a finger is inside: release what is still pressed.
    void OnDisable()
    {
        foreach (HapticFingerTrigger touch in touching)
        {
            if (touch != null) touch.RemoveHaptics();
        }
        touching.Clear();
    }
}

Release on reconnect

A glove whose link dropped is still pressing whatever it was told last. This releases it as soon as it is back.

csharp
using UnityEngine;
using HaptGlove;
using HexR;

// A glove whose Bluetooth link dropped keeps its last pressure. When it
// reconnects, release everything before anything else is sent.
public class ReleaseOnReconnect : MonoBehaviour
{
    void Start()
    {
        HexRManager.Instance.leftHand.onBluetoothConnected += ReleaseAll;
        HexRManager.Instance.rightHand.onBluetoothConnected += ReleaseAll;
    }

    void OnDestroy()
    {
        if (HexRManager.Instance == null) return;
        HexRManager.Instance.leftHand.onBluetoothConnected -= ReleaseAll;
        HexRManager.Instance.rightHand.onBluetoothConnected -= ReleaseAll;
    }

    void ReleaseAll(HaptGloveHandler.HandType hand)
    {
        HaptGloveHandler glove = hand == HaptGloveHandler.HandType.Left
            ? HexRManager.Instance.leftHand
            : HexRManager.Instance.rightHand;
        glove.ReleaseAllChannels();
    }
}

Where to go next

Integrating into an existing app? Start with HexRInteractableHaptics before the lower-level PressureTrackerMain or HaptGloveHandler.