VerseGrip – Anleitung zur Positionssteuerung
In diesem Tutorial wird gezeigt, wie man mithilfe der Drehfunktion von VerseGrip die Position des Cursors auf dem Gerät „ Inverse3 “ direkt steuern und dabei den Unity-Hauptthread umgehen kann, um eine hohe Aktualisierungsrate zu erzielen.
Einführung
und Einführungsleitfaden Im Gegensatz zu der dort beschriebenen Methode (die mit einer Standard-Aktualisierungsrate von 60 Hz läuft) zielt dieses Tutorial darauf ab, die Position des Cursors unter Inverse3 anhand der Drehung des VerseGrip-Geräts dynamisch mit einer höheren Frequenz (1–4 kHz) anzupassen.
Dies geschieht durch die Nutzung von durch haptische Threads ausgelösten DeviceStateChanged Das Ereignis wurde realisiert.
Szeneneinstellungen
Erstellen Sie zunächst ein „Haptic Rig“:„GameObject“ > „ Haply “ > „Haptic Rig (one hand)“. Die genauen Schritte finden Sie im Einführungsleitfaden.
VerseGripPositionControl-Komponente
Erstellen Sie eine Datei mit dem Namen VerseGripPositionControl.cs das neue C#-Skript und fügen Sie es an Haptischer Ursprung auf dem Spielobjekt.
In VerseGripPositionControl In der Klasse sind folgende Eigenschaften definiert:
public Inverse3 inverse3;
public VerseGrip verseGrip;
[Range(0, 1)]
public float speed = 0.5f;
[Range(0, 0.2f)]
public float movementLimitRadius = 0.2f;
private Vector3 _targetPosition;
- inverse3: Die Verweise auf „ Inverse3 “-Geräte werden über den Inspector eingerichtet.
- verseGrip: Verweis auf das VerseGrip-Gerät zur Cursorsteuerung.
- Geschwindigkeit: Die Bewegungsgeschwindigkeit des Cursors.
- movementLimitRadius: Die maximale Entfernung, um die sich der Cursor von seiner Ausgangsposition wegbewegen kann.
- _targetPosition: Die Zielposition, in deren Richtung sich der Cursor bewegt.
Die „Awake“-Methode
in Awake In der Methode: Registrierung Ready Ereignis, um die Zielposition des Cursors entsprechend dem Arbeitsbereichszentrum des Geräts unter Inverse3 zu initialisieren:
private void Awake()
{
inverse3.Ready.AddListener((inverse3Controller, args) =>
{
_targetPosition = inverse3Controller.WorkspaceCenterLocalPosition;
});
}
Solange das Gerät noch nicht einsatzbereit ist, kann der Mittelpunkt des Arbeitsbereichs nicht ermittelt werden, da die Konfiguration für die linke bzw. rechte Hand noch nicht festgelegt wurde.
Umsetzung OnDeviceStateChanged Vorgehensweise zur Berechnung der Zielposition des Cursors anhand der Dreh- und Tasteneingaben von VerseGrip:
private void OnDeviceStateChanged(object sender, VerseGripEventArgs args)
{
var verseGrip = args.DeviceController;
// Calculate the direction based on the VerseGrip's rotation
var direction = verseGrip.Orientation * Vector3.forward;
// Check if the VerseGrip button is pressed down
if (verseGrip.GetButtonDown())
{
// Initialize target position
_targetPosition = inverse3.CursorLocalPosition;
}
// Check if the VerseGrip button is being held down
if (verseGrip.GetButton())
{
// Move the target position toward the grip direction
_targetPosition += direction * (0.0001f * speed);
// Clamp the target position within the movement limit radius
var workspaceCenter = inverse3.WorkspaceCenterLocalPosition;
_targetPosition = Vector3.ClampMagnitude(_targetPosition - workspaceCenter, movementLimitRadius)
+ workspaceCenter;
}
// Move cursor to new position
inverse3.SetCursorLocalPosition(_targetPosition);
}
in OnEnable und OnDisable Anmeldung und Abmeldung DeviceStateChanged Ereignis.
/// Subscribes to the DeviceStateChanged event.
private void OnEnable()
{
verseGrip.DeviceStateChanged += OnDeviceStateChanged;
}
/// Unsubscribes from the DeviceStateChanged event.
private void OnDisable()
{
verseGrip.DeviceStateChanged -= OnDeviceStateChanged;
}
Spielablauf
- Befestigen Sie das Gerät „ Inverse3 “ und stellen Sie sicher, dass ausreichend Bewegungsfreiheit vorhanden ist.
- Wechseln Sie in den Wiedergabemodus (Play Mode) und halten Sie den Cursor „ Inverse3 “ gedrückt.
- Drehen Sie den VerseGrip und beobachten Sie, wie sich der Cursor in der Unity-Szene bewegt – seine Ausrichtung entspricht direkt der Ausrichtung des VerseGrip.
- Durch Drücken der Taste am VerseGrip bewegt sich der Cursor von „ Inverse3 “ in die Richtung, in die der VerseGrip gedreht wird, und zeigt so die Auswirkungen der Steuerung in Echtzeit an.

Das Bild zeigt ein Cursor-Modell, dessen Vorwärtsachse zur besseren Erkennbarkeit hervorgehoben ist. Weitere Informationen zum Anpassen von Cursor-Modellen finden Sie in der Cursor-Dokumentation.
Quelldatei
Die in diesem Beispiel verwendete endgültige Szene sowie alle zugehörigen Dateien können über den Unity-Paket-Manager aus den „Tutorials“-Beispielen importiert werden.
VerseGripPositionControl.cs
/*
* Copyright 2024 Haply Robotics Inc. All rights reserved.
*/
using Haply.Inverse.DeviceControllers;
using Haply.Inverse.DeviceData;
using UnityEngine;
namespace Haply.Samples.Tutorials._6_VerseGripPositionControl
{
/// <summary>
/// Demonstrates how to control the device cursor position using the VerseGrip.
/// </summary>
public class VerseGripPositionControl : MonoBehaviour
{
public Inverse3Controller inverse3;
public VerseGripController verseGrip;
[Tooltip("Cursor moving speed")]
[Range(0, 1)]
public float speed = 0.5f;
[Tooltip("Maximum radius for cursor movement")]
[Range(0, 0.1f)]
public float movementLimitRadius = 0.075f;
private Vector3 _targetPosition; // Target position for the cursor
private void Awake()
{
inverse3.Ready.AddListener((inverse3Controller, args) =>
{
_targetPosition = inverse3Controller.WorkspaceCenterLocalPosition;
});
}
/// <summary>
/// Subscribes to the DeviceStateChanged event.
/// </summary>
private void OnEnable()
{
verseGrip.DeviceStateChanged += OnDeviceStateChanged;
}
/// <summary>
/// Unsubscribes from the DeviceStateChanged event.
/// </summary>
private void OnDisable()
{
verseGrip.DeviceStateChanged -= OnDeviceStateChanged;
inverse3.Release();
}
private void OnDeviceStateChanged(object sender, VerseGripEventArgs args)
{
var verseGrip = args.DeviceController;
// Calculate the direction based on the VerseGrip's rotation
var direction = verseGrip.Orientation * Vector3.forward;
// Check if the VerseGrip button is pressed down
if (verseGrip.GetButtonDown())
{
// Initialize target position
_targetPosition = inverse3.CursorLocalPosition;
}
// Check if the VerseGrip button is being held down
if (verseGrip.GetButton())
{
// Move the target position toward the grip direction
_targetPosition += direction * (0.0001f * speed);
// Clamp the target position within the movement limit radius
var workspaceCenter = inverse3.WorkspaceCenterLocalPosition;
_targetPosition = Vector3.ClampMagnitude(_targetPosition - workspaceCenter, movementLimitRadius)
+ workspaceCenter;
}
// Move cursor to new position
inverse3.SetCursorLocalPosition(_targetPosition);
}
}
}