Microtube 文档
EN中文
开发者 / Unity / 触觉设置

Unity 触觉设置

HEXR 触觉的工作原理,如何通过代码或无需代码添加触觉,以及如何设计出手感恰当的触觉。

触觉的工作原理

无论由什么触发,每个触觉都经过同样的路径:

无需代码添加触觉

三个组件即可覆盖大多数物体。像添加其他组件一样,在 Inspector 中添加它们即可。

感受你抓取的物体——HexRInteractableHaptics

建议从这里入手。当你的 XR SDK 抓取或悬停在该物体上时,它会按压手指。

  1. 将它添加到可交互组件旁边

    添加到已带有 XR Grab Interactable(OpenXR)或 Meta 的 Grabbable 和 Hand Grab Interactable 的物体上。Backend 保持为 Auto 即可。

  2. 选择触发时机

    将 Fire On 设为 Select(抓取期间)、Hover(手靠近期间)或 Select And Hover。

  3. 选择手指和强度

    勾选要按压的手指并设置 Strength,范围从 10(几乎感觉不到)到 60(紧实)。开启 Follow Grip 后,强度会根据手指合拢的程度,在 Min Strength 与 Strength 之间缩放。

让表面摸起来像真实的东西——SpecialHaptics

将它放在触发碰撞体上,然后点击 Auto Find Hand Physics。任何碰到该碰撞体的手指,都会感受到你在 Type Of Haptics 中选择的效果——无需抓取,也无需手部靠近检测。

效果手感
CustomHaptics触碰期间持续施加压力
CustomVibrations以设定的频率和强度振动
FountainEffect流水
RainDropEffect雨滴落在手掌上
HeartBeatEffect心跳,规律或不规律
HandSqueezeEffect手在该区域内握拢时触发事件

对于两种自定义效果,请设置 Haptic Pressure;如果是振动,还需设置 Vibrations Frequency Value。

交互器无法覆盖的物体——ProximityCheck

它本身不触发任何触觉:它告诉 HEXR 手就在附近,从而放行该物体上的其他触觉。将它与触发碰撞体一起添加,然后点击 Auto Set Up。

用指尖按下的按钮、手指弯曲事件等更多用法:我需要哪个组件?

通过代码触发触觉

对于游戏事件、触觉序列或组件无法覆盖的情况,可直接调用该手的 Pressure Controller(压力控制器)。在脚本中添加一个 PressureTrackerMain 字段,然后将场景中的 Left 或 Right Pressure Controller 拖入。

单根手指

csharp
// using HaptGlove; using HexR;
// hand: a PressureTrackerMain field with a Pressure Controller dragged in

// Pressure: finger, on/off, intensity 0.1-1, ramp speed 0.1-1, skip hand-near check
hand.CustomSingleHaptics(Haptics.Finger.Index, true, 0.5f, 1f, false);

// Vibration: finger, on/off, intensity 0.1-1, frequency 0.1-40 Hz, skip hand-near check
hand.CustomSingleVibrations(Haptics.Finger.Palm, true, 0.7f, 12f, false);

// The components' 10-60 strength scale, as the 0.1-1 intensity above
float intensity = PressureTrackerMain.StrengthToIntensity(30f);

最后一个参数用于跳过手部靠近检测。如果按压是为了响应你自己的事件而非触碰,请传入 true。

多根手指,同一设置

传入六个开/关值,每个通道一个,顺序始终为拇指、食指、中指、无名指、小指、手掌。这些调用没有跳过检测的参数,因此只有在手靠近物体时才会触发。

csharp
// One entry per channel: Thumb, Index, Middle, Ring, Pinky, Palm
bool[] grip = { true, true, true, false, false, false };   // thumb, index and middle

hand.TriggerCustomHapticsIncrease(grip, 0.6f, 1f);   // pressure 0.1-1, ramp speed 0.1-1
hand.TriggerCustomlVibrations(grip, 0.7f, 12f);      // intensity 0.1-1, frequency 0.1-40 Hz
                                                     // (the stray "l" is in the real name)

hand.TriggerAllHapticsIncrease(0.5f);                // every channel, pressure 0.1-1
hand.TriggerAllVibrations(12f);                      // every channel, frequency
hand.TriggerPinchPressure(0.6f);                     // thumb and index together

每根手指单独设置

为全部六个通道构建一条命令并直接发送给手套:只需一次蓝牙写入,且不经过手部靠近检测。每个数组都必须为每根手指提供一个条目,顺序相同,否则调用会抛出错误。

csharp
HaptGloveHandler glove = HexRManager.Instance.rightHand;   // or leftHand

// All six channels, always in this order
Haptics.Finger[] fingers = { Haptics.Finger.Thumb,  Haptics.Finger.Index,
                             Haptics.Finger.Middle, Haptics.Finger.Ring,
                             Haptics.Finger.Pinky,  Haptics.Finger.Palm };
bool[]  on          = { true, true, true, true, true, true };   // false leaves a channel out
float[] intensities = { 0.3f, 0.9f, 0.9f, 0.6f, 0.4f, 0.8f };
float[] speeds      = { 1f,   1f,   1f,   1f,   1f,   1f   };
glove.BTSend(glove.haptics.HEXRPressure(fingers, on, intensities, speeds));

// Vibration: here frequency comes BEFORE intensity. 0 Hz is clamped to 0.1 Hz, not off.
float[] freqs = { 3f, 12f, 12f, 6f, 3f, 3f };
glove.BTSend(glove.haptics.HEXRVibration(fingers, on, freqs, intensities));

松开

csharp
hand.CustomSingleHaptics(Haptics.Finger.Index, false, 0f, 1f, true);    // one finger's pressure
hand.CustomSingleVibrations(Haptics.Finger.Palm, false, 0f, 12f, true);  // one finger's vibration
hand.RemoveIndexHaptics();      // one finger: RemoveThumbHaptics() ... RemovePalmHaptics()
hand.RemoveAllHaptics();        // every channel's pressure on this hand
hand.RemoveAllVibrations();     // every channel's vibration on this hand
glove.ReleaseAllChannels();     // everything on the glove, in one write
施加之后务必释放

手套会持续施加最后收到的压力,直到收到释放命令;手套上没有任何部件会自行松开。自 0.9.4 起,Unity 插件包会在应用退出、暂停或断开手套连接时释放所有通道,但如果应用崩溃或蓝牙连接中断,就没有任何办法释放;Python 库也不会替你释放任何通道。如果手套一直保持按压,请关闭手臂模块。

释放时,可将最后一个参数设为 true,或调用 Remove… 系列方法或 ReleaseAllChannels()。经过手部靠近检测的释放调用,在手移开后会被丢弃——RemovePinchPressure() 就是其中之一,因此请在它之后再调用 RemoveAllHaptics()。

可直接复制的完整脚本:在自定义事件中按压手指和按压触碰到物体的手指。所有方法都列在 PressureTrackerMain 下。

设计触觉

两种模式,以及几项会改变手感的设置:

模式设置作用
压力强度(Intensity)0.1–1按压力度:约 15 至 50 kPa
压力速度(Speed)0.1–1达到目标压力的快慢。设为 1 时,约 0.3 s 达到最大按压;设为 0.1 时,慢十倍
振动0.1–5 Hz可以数清的独立脉冲。强度决定每个脉冲的按压力度
振动5–40 Hz持续的嗡嗡振动。强度决定每个脉冲的持续时长

如需塑造节奏,还可以使用慢脉冲和计数脉冲——参见通道与参数。

提示