Aller au contenu principal

Tutoriel sur le contrôle de position VerseGrip

Ce tutoriel explique 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 afin d'obtenir des 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 rafraîchissement standard (60 Hz), 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 à 4 kHz). Pour ce faire, on exploite 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 » (une main), comme indiqué dans le Guide de démarrage.

Composant VerseGripPositionControl​

Créez un nouveau script C# nommé VerseGripPositionControl.cs et attachez-le à l'objet du jeu Origine haptique. 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 contrôler le 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;
});
}

Tant que l'appareil n'est pas 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 du VerseGrip et des actions sur les 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);
}

Inscrivez-vous à l'événement et désinscrivez-vous 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 , en veillant à ce qu'il dispose d'un espace suffisant pour se déplacer.
  • Activez le mode Lecture 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 du VerseGrip permet au curseur Inverse3 de se déplacer dans le sens de la rotation du VerseGrip, ce qui illustre le contrôle en temps réel.

balle mobile avec VerseGrip

L'image illustre le modèle de curseur, dont l'axe avant est mis en évidence pour plus de clarté. Pour plus de détails sur la personnalisation du modèle de curseur, consultez la documentation relative aux curseurs.

Fichiers sources​

La scène finale et tous les fichiers associés utilisés dans cet exemple peuvent être importés à partir de 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);
}
}
}