Godot 插件架构与 API
HexR Godot 插件的构建方式、GDScript API,以及它与 Unity 插件包的对应关系。
插件包含哪些内容
| 文件夹 | 内容 |
|---|---|
core/ | 手套协议(帧编码器、遥测解码器)、HaptGloveHandler、Haptics、SceneLoader 以及 HexR 自动加载 |
transport/ | 低功耗蓝牙:Android(HexRBle Java 插件)、Windows(HexRBleWinRT 扩展),以及用于测试和其他平台的模拟手套 |
hands/、haptics/、components/、interaction/ | 被追踪的手及其 HapticFingerTrigger、PressureTrackerMain、场景节点、XR Tools 绑定 |
ui/、remote/、editor/ | 悬浮菜单、HexR Remote、HexR 菜单、HexR Tools 停靠面板、检查器(Inspector)插件以及 Android 导出步骤 |
全部使用 GDScript 编写,因此可在标准版(非 .NET)Godot 上运行。只有在 Godot 无法访问蓝牙或屏幕捕获的地方才使用原生代码:一个 Java Android 插件和一个 C++/WinRT 扩展,二者均由 CI 构建,并包含在发布的 zip 包中。
协议兼容性
该插件发送的字节与 Unity 插件包完全相同:其编码器以 32 位浮点数执行与 Unity 相同的运算,测试会将 555 个命令帧与 Unity 插件包的输出逐一比对。它使用相同的 HexR Remote 协议,因此 HexR Companion 同样适用于 Godot 和 Unity 应用。
连接手套
- 连接时,会扫描
HaptGloveAR Left/Right,或直接连接它记住的手套(按平台分别保存在user://hexr.cfg中)。 - 每次连接时订阅一次手套读数,与头显协商其允许的最大数据包,并按帧边界切分每次写入,使其不超出该大小。
- 连接失败后,会在 1、2、4、8 秒后重试,最长持续一分钟;20 秒的看门狗会重启无响应的连接尝试;手套掉线后会自动重新连接。
- 在 Android 上,命令最多每 100 ms 批量发送一次。释放命令不经过队列。应用暂停时,由于脚本停止运行,Java 插件会自行释放手套。
GDScript API
大多数游戏会用到的调用。所有类、信号、属性和方法都列在插件的 API 参考 ↗中,也可以在 Godot 内置帮助中查看:按 F1 并搜索 HexR。
HexR(自动加载)
connect_hand(hand)、disconnect_hand(hand)、toggle_hand(hand)、begin_connect(hand)、connect_left_bt()、connect_right_bt()、is_hand_connected(hand)、is_hand_connecting(hand)、glove(hand)、controller(hand)、tracked_hand(hand)、finger_use(hand);两只手套分别为 left_hand 和 right_hand。信号:glove_connected、glove_disconnected、glove_connect_failed、connect_attempt_ended、battery_state_changed、pump_changed、status_changed、device_found。
HaptGloveHandler
bt_send(bytes)、bt_connection()、bt_disconnection()、release_all_channels()、release_channels(fingers)、get_battery_level()、get_air_pressure_kpa()、get_finger_position()、set_battery_level_update_interval(seconds)、remember_device(id)、forget_device()、connect_to_device(id);属性:which_hand、haptics、ble_connected、status_text、optional_custom_device_name、release_when_paused。信号:bluetooth_connected、bluetooth_disconnected、bluetooth_connection_failed、battery_state_changed、pump_changed。
PressureTrackerMain
single_index_haptic(intensity) … single_palm_haptic、remove_index_haptics() …、custom_single_haptics、custom_single_vibrations、trigger_all_haptics_increase、trigger_custom_haptics_increase、trigger_pinch_pressure、trigger_all_vibrations、trigger_custom_vibrations、trigger_pulse_it、remove_all_haptics、remove_all_vibrations、is_hand_near(),以及静态方法 strength_to_intensity(strength);读数:thumb_pressure … palm_pressure 和 tank_pressure。
SceneLoader
与 Unity 一样是静态方法:load_scene(name_or_index)、load_next_scene()、load_previous_scene()、reload_current_scene()、get_current_scene_name()、get_current_scene_index(),作用于 hexr/scenes 中列出的场景。
从 Unity 迁移
各个类沿用 Unity 插件包的名称:HaptGloveHandler、Haptics、PressureTrackerMain、HapticFingerTrigger、HexRTrackedHand、FingerUseTracking、SpecialHaptics、ProximityCheck、HexRGrabbable、HexRPhysicalButton、HexRUsable、HexRInteractableHaptics、HexRFloatingMenu、HexRRemote、HaptGloveCollidersVisualizer、SceneLoader。它们的成员沿用 Unity 的名称,改为 Godot 的 snake_case 写法,因此 TriggerPinchPressure 对应 trigger_pinch_pressure,typeOfHaptics 对应 type_of_haptics。编辑器也保持一致:HexR 菜单提供与 Unity 相同的菜单项,HexR Tools 停靠面板有三个标签页(Haptics Tester、HexR Setup、Project Setup)。Godot 与 Unity 的不同之处及原因如下:
| Unity 插件包 | Godot 插件 | 原因 |
|---|---|---|
HexRManager.Instance | HexR 自动加载(或 HexRManager.instance) | Godot 的单例通过自动加载(autoload)实现 |
Connect / Disconnect / IsConnected(hand) | connect_hand / disconnect_hand / is_hand_connected(hand) | 每个 Godot 对象本身已有 connect、disconnect 和 is_connected |
TriggerAllHapticsIncrease(0.5f) | trigger_all_haptics_increase(0.5) | Godot 使用 snake_case;枚举值使用大写(UPPER_CASE) |
HEXRPressure 重载 | hexr_pressure、hexr_pressure_multi、hexr_vibration_ramped 等 | GDScript 不支持重载 |
UnityEvents OnGrab、onPressed | 信号 grabbed、pressed | Godot 的信号机制 |
HexRGrabbable 上的 Gravity | gravity_on_release | Area3D 已有 gravity 属性 |
HapticFingerTrigger.FingerType | 所有地方统一使用 Haptics.Finger | 只有一种通道顺序,即手套本身的顺序 |
| Build Settings 场景列表 | Project Settings → HexR → Scenes(hexr/scenes) | Godot 没有 Build Settings 列表 |
| Auto Setup、手部根节点(hand roots) | 无需设置 | 手指触发器直接跟随 OpenXR 手部追踪器 |
| XRI / Meta Interaction SDK 后端 | Godot XR Tools | Godot 的 XR 工具包 |
| Package Manager 的 git URL | 发布版 zip,解压到 addons/ | Godot 以文件夹形式安装插件 |
如果项目中已有同名的类(例如名为 SceneLoader 的自动加载),Godot 会报出“hides a global script class”错误:请将你自己的类改名。
HexR Remote
添加一个 HexRRemote 节点后,HexR Companion 的 Headsets 标签页就能在同一 Wi-Fi 网络中找到该应用:可查看双手手套的状态和压力、连接与释放、切换场景、发送你的命令,并可在 Android 上查看头显的画面和声音(需佩戴者接受捕获提示)。该节点在场景切换后依然保留。
# A button in the HexR Companion's Headsets tab, while this node is in the scene.
func _ready() -> void:
HexRRemote.register_command("reset", "Reset demo", reset_demo)
func _exit_tree() -> void:
HexRRemote.unregister_command("reset")HexR Remote 没有身份验证:同一 Wi-Fi 网络中任何拥有 HexR Remote 客户端的人都能控制手套。参加活动时请自带专用路由器。
测试方式
每次推送都会在 Godot 4.6 和 4.7.2 上运行 GDScript 测试,并分别使用 Jolt 和 Godot Physics:包括逐字节一致的帧、解码器、针对模拟手套的完整连接流程、通过真实物理重叠检测的场景节点,以及通过真实套接字运行的 HexR Remote,后者还会用 Unity 插件包自带的 Remote 探针再次检查。Android 插件和 Windows 扩展在 CI 中构建,并有各自的测试。