Anleitung zur Positionssteuerung mit VerseGrip
Dieses Tutorial zeigt, wie man die Drehung des VerseGrip nutzt, um die Cursorposition eines Geräts Inverse3 direkt zu steuern, wobei der Hauptthread von Unity für Aktualisierungen mit hoher Frequenz umgangen wird.
Einführung
Im Gegensatz zu der im Leitfaden für den Einstieg, das mit einer Standard-Bildwiederholfrequenz (60 Hz) arbeitet, zielt dieses Tutorial darauf ab, die Position des Cursors Inverse3 dynamisch entsprechend der Drehung des VerseGrip-Geräts mit einer höheren Frequenz (1–4 kHz) anzupassen.
Dies wird durch die Nutzung des Ereignisses DeviceStateChanged, ausgelöst durch den haptischen Thread.
Einrichtung der Szene
Erstellen Sie zunächst ein Haptic Rig: „GameObject“ > „ Haply “ > „Haptic Rig (one hand)“, wie in der Einführungsanleitung beschrieben.
Komponente „VerseGripPositionControl“
Erstellen Sie ein neues C#-Skript mit dem Namen VerseGripPositionControl.cs und befestigen Sie es am Spielobjekt Haptischer Ursprung.
Legen Sie in der Klasse die folgenden Eigenschaften fest VerseGripPositionControl :
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 : Verweis auf das Gerät „ Inverse3 “, das im Inspektor definiert ist.
- verseGrip: Bezieht sich auf das VerseGrip-Gerät, das zur Steuerung des Cursors verwendet wird.
- Geschwindigkeit: Bewegungsgeschwindigkeit des Cursors.
- movementLimitRadius: Maximale Entfernung, die der Cursor von seiner Ausgangsposition aus zurücklegen kann.
- _targetPosition: Zielposition, zu der sich der Cursor bewegt.
Awake-Methode
In der Methode Awake, tragen Sie den Termin ein Ready So legen Sie die Zielposition des Cursors entsprechend der Mitte des Arbeitsbereichs des Geräts fest Inverse3 :
private void Awake()
{
inverse3.Ready.AddListener((inverse3Controller, args) =>
{
_targetPosition = inverse3Controller.WorkspaceCenterLocalPosition;
});
}
Bevor das Gerät betriebsbereit ist, steht die Mitte des Arbeitsbereichs nicht zur Verfügung, da die Seitenausrichtung noch nicht festgelegt ist.
Implementieren Sie die Methode OnDeviceStateChanged Um die Zielposition des Cursors anhand der Drehung des VerseGrip und der Tastenbetätigungen zu berechnen:
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);
}
Veranstaltung anmelden und abmelden DeviceStateChanged dans OnEnable et OnDisable.
/// Subscribes to the DeviceStateChanged event.
private void OnEnable()
{
verseGrip.DeviceStateChanged += OnDeviceStateChanged;
}
/// Unsubscribes from the DeviceStateChanged event.
private void OnDisable()
{
verseGrip.DeviceStateChanged -= OnDeviceStateChanged;
}
Ablauf
- Befestigen Sie das Gerät Inverse3 und stellen Sie sicher, dass es genügend Bewegungsfreiheit hat.
- Aktivieren Sie den Wiedergabemodus und halten Sie den Cursor auf „ Inverse3 “ gedrückt.
- Drehen Sie den VerseGrip, um zu beobachten, wie sich der Cursor in der Unity-Szene bewegt – dies entspricht direkt der Ausrichtung des VerseGrip.
- Durch Drücken der VerseGrip-Taste bewegt sich der Schieberegler „ Inverse3 “ in Drehrichtung des VerseGrip, wodurch die Steuerung in Echtzeit veranschaulicht wird.

Die Abbildung zeigt das Cursor-Modell, wobei die vordere Achse zur besseren Übersichtlichkeit hervorgehoben ist. Weitere Informationen zur Anpassung des Cursor-Modells finden Sie in der Dokumentation zu den Schiebereglern.
Quelldateien
Die Schlussszene und alle zugehörigen Dateien, die in diesem Beispiel verwendet werden, können aus dem Beispiel „Tutorials“ im Unity Package Manager 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);
}
}
}