Tutoriel sur le contrôle de position VerseGrip
Ce tutoriel montre comment utiliser la rotation du VerseGrip pour contrôler directement la position du curseur d'un appareil Inverse3, en contournant le thread principal de Unity pour les mises à jour à haute fréquence.
Introduction
Contrairement à la méthode présentée dans le Guide de démarrage, qui fonctionne à une fréquence de mise à jour standard (60Hz), ce tutoriel vise à ajuster dynamiquement la position du curseur Inverse3 en fonction de la rotation de l'appareil VerseGrip à une fréquence plus élevée (1~4kHz).
Ceci est réalisé en exploitant l'événement DeviceStateChanged, déclenché par le thread haptique.
Configuration de la scène
Commencez par créer un Haptic Rig : GameObject > Haply > Haptic Rig (one hand), comme décrit dans le Guide de démarrage.
Composant VerseGripPositionControl
Créez un nouveau script C# nommé VerseGripPositionControl.cs et attachez-le à l'objet de jeu Haptic Origin.
Définissez les propriétés suivantes dans la classe 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 : référence à l'appareil Inverse3, défini dans l'inspecteur.
- verseGrip : référence à l'appareil VerseGrip utilisé pour le contrôle du curseur.
- speed : vitesse de déplacement du curseur.
- movementLimitRadius : distance maximale que le curseur peut parcourir à partir de sa position initiale.
- _targetPosition : position cible vers laquelle le curseur se déplace.
Méthode Awake
Dans la méthode Awake, enregistrez l'événement Ready pour initialiser la position cible du curseur en fonction du centre de l'espace de travail de l'appareil Inverse3 :
private void Awake()
{
inverse3.Ready.AddListener((inverse3Controller, args) =>
{
_targetPosition = inverse3Controller.WorkspaceCenterLocalPosition;
});
}
Avant que l'appareil soit prêt, le centre de l'espace de travail n'est pas disponible, car la latéralité n'est pas encore déterminée.
Implémentez la méthode OnDeviceStateChanged pour calculer la position cible du curseur en fonction de la rotation de VerseGrip et des entrées des boutons :
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);
}
Enregistrez et désenregistrez l'événement 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;
}
Déroulement
- Fixez l'appareil Inverse3 et assurez-vous qu'il dispose d'un espace suffisant pour se déplacer.
- Activez le Play Mode et maintenez le curseur Inverse3.
- Faites tourner VerseGrip pour observer le déplacement du curseur dans la scène Unity, qui correspond directement à l'orientation de VerseGrip.
- Appuyer sur le bouton de VerseGrip permet au curseur Inverse3 de se déplacer dans la direction de la rotation de VerseGrip, ce qui illustre le contrôle en temps réel.

L'image illustre le Cursor Model avec son axe avant mis en évidence pour plus de clarté. Pour plus de détails sur la personnalisation du Cursor Model, consultez la documentation sur les curseurs.
Fichiers sources
La scène finale et tous les fichiers associés utilisés par cet exemple peuvent être importés depuis l'exemple Tutorials du Package Manager de Unity.
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);
}
}
}