Zum Hauptinhalt springen

VerseGrip-Anleitung zur Positionssteuerung

Dieses Tutorial zeigt, wie Sie die Drehung des VerseGrip nutzen können, um die Cursorposition eines „ Inverse3 “-Geräts direkt zu steuern und dabei den Hauptthread von Unity für hochfrequente Aktualisierungen zu umgehen.

Einführung​

Anders als bei der Methode aus der Anleitung „Erste Schritte“, das mit einer üblichen Aktualisierungsfrequenz (60 Hz) arbeitet, zielt dieses Tutorial darauf ab, die Cursorposition des Inverse3 dynamisch anhand der Drehung des VerseGrip-Geräts mit einer höheren Frequenz (1–4 kHz) anzupassen. Dies wird erreicht, indem das Ereignis DeviceStateChanged genutzt wird, das durch den haptischen Thread ausgelöst wird.

Szenenaufbau​

Beginnen Sie damit, ein Haptic Rig zu erstellen: „GameObject“ > „ Haply “ > „Haptic Rig (one hand) “, wie in der Anleitung „Erste Schritte“ beschrieben.

Komponente „VerseGripPositionControl“​

Erstellen Sie ein neues C#-Skript mit dem Namen VerseGripPositionControl.cs und fügen Sie es dem GameObject hinzu Haptischer Ursprung an. Definieren Sie in der Klasse VerseGripPositionControl die folgenden Eigenschaften:

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 „ Inverse3 “-Gerät, das im Inspector festgelegt wird.
  • verseGrip: Verweis auf das VerseGrip-Gerät, das zur Cursorsteuerung verwendet wird.
  • Geschwindigkeit: Die Geschwindigkeit, mit der sich der Cursor bewegt.
  • movementLimitRadius: Maximaler Abstand, den der Cursor von seiner Ausgangsposition entfernt sein darf.
  • _targetPosition: Zielposition, auf die sich der Cursor bewegt.

Methode Awake​

Registrieren Sie sich in der Methode Awake das Ereignis Ready, um die Zielposition des Cursors anhand des Mittelpunkts des Arbeitsraums des „ Inverse3 “-Geräts zu initialisieren:

private void Awake()
{
inverse3.Ready.AddListener((inverse3Controller, args) =>
{
_targetPosition = inverse3Controller.WorkspaceCenterLocalPosition;
});
}

Bevor das Gerät betriebsbereit ist, steht der Mittelpunkt des Arbeitsraums noch nicht zur Verfügung, da die Händigkeit noch nicht festgelegt ist.

Implementieren Sie die Methode OnDeviceStateChanged, um die Zielposition des Cursors anhand der Drehung des VerseGrip und der Tastatureingabe 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);
}

Registrieren Sie die Veranstaltung DeviceStateChanged in OnEnable und führen Sie die Registrierung in OnDisable wieder auf.

/// Subscribes to the DeviceStateChanged event.
private void OnEnable()
{
verseGrip.DeviceStateChanged += OnDeviceStateChanged;
}

/// Unsubscribes from the DeviceStateChanged event.
private void OnDisable()
{
verseGrip.DeviceStateChanged -= OnDeviceStateChanged;
}

Spielverlauf​

  • Befestigen Sie das Gerät Inverse3 , und stellen Sie sicher, dass es genügend Bewegungsfreiheit hat.
  • Starten Sie den Wiedergabemodus und halten Sie den Cursor auf „ Inverse3 “.
  • Drehen Sie das VerseGrip-Gerät, um die Bewegung des Cursors in der Unity-Szene zu beobachten, die genau der Ausrichtung des VerseGrip entspricht.
  • Durch Drücken der Taste am VerseGrip kann sich der Cursor „ Inverse3 “ in Richtung der Drehung des VerseGrip bewegen. Dies veranschaulicht die Steuerung in Echtzeit.

Sich bewegender Ball mit Versegrip

Die Abbildung zeigt das Cursor-Modell mit hervorgehobener Vorwärtsachse, um einen besseren Überblick zu ermöglichen. Weitere Details zur Anpassung des Cursor-Modells finden Sie in der Cursor-Dokumentation.

Quelldateien​

Die fertige Szene und alle zugehörigen Dateien dieses Beispiels können über die Beispiel-Tutorials im Paketmanager von Unity 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);
}
}
}