Petit tutoriel sur le contrôle de position
Ce tutoriel montre comment contrôler la position du curseur d'un périphérique « Inverse3 » dans une scène Unity à l'aide d'objets de jeu dynamiques. Son contenu s'appuie sur les concepts présentés dans le guide de démarrage.
Présentation
Inverse3 L'appareil prend en charge deux modes de commande :Contrôle de la forceetContrôle de position。
Le premier ajuste l'intensité de la force en fonction de la position du curseur, tandis que le second contrôle directement la position du curseur.
Ce tutoriel reprend Tutoriel sur le retour de force dans les scènes dynamiques La mise en scène de cette scène met l'accent sur FixedUpdate Utilisé dans la méthode CursorSetPosition, afin que le curseur de l'appareil puisse suivre les objets du jeu en mouvement.
Mise en scène
Veuillez d'abord suivre les instructions suivantes : Tutoriel sur le retour de force dans les scènes dynamiques Configurer les paramètres de scénario décrits ci-dessus, qui comprennent notamment un Dispositif haptique ainsi que par MovableObject Contrôlé par des composants Balle en mouvement Objets du jeu.
Implémenter le composant SpherePositionControl
Va Balle en mouvement Sur les objets du jeu SphereForceFeedback Remplacer le composant par un élément nommé SpherePositionControl.cs Un nouveau script C#.
Dans SpherePositionControl Les propriétés suivantes sont définies dans la classe :
public Inverse3 inverse3;
public float minSyncDistance = 0.05f;
private bool _isCursorSynchronized;
- inverse3: Référence aux composants de l'appareil « Inverse3 », configurée via l'Inspector.
- minSyncDistance: seuil de distance minimal requis pour activer la synchronisation du curseur.
- _isCursorSynchronized: indicateur précisant si le déplacement du curseur est synchronisé avec celui de la « Moving Ball ».
Logique de synchronisation
Méthode permettant d'activer et de désactiver la synchronisation du curseur en fonction de la proximité avec la « Moving Ball » :
private void StartSynchronizeCursor()
{
var cursorPosition = inverse3.Cursor.transform.position;
GetComponent<MovableObject>().SetTargetPosition(cursorPosition, teleport: true);
_isCursorSynchronized = true;
}
private void StopSynchronizeCursor()
{
_isCursorSynchronized = !inverse3.Release();
}
On utilise ici
MovableObject.SetTargetPosition(position, teleport:true), cela va MovingBall Se téléporter à l'emplacement du curseur.
Les méthodes `Update` et `FixedUpdate`
à Update Dans cette méthode, en fonction de la position du curseur et de Balle en mouvement Distance entre les curseurs pour la synchronisation :
private void Update()
{
var distance = Vector3.Distance(inverse3.CursorPosition, transform.position);
if (!_isCursorSynchronized && distance <= minSyncDistance)
{
StartSynchronizeCursor();
}
else if (_isCursorSynchronized && distance > minSyncDistance)
{
StopSynchronizeCursor();
}
}
à FixedUpdate Dans ce cas, si la synchronisation est activée, la position du curseur est mise à jour pour correspondre à Balle en mouvement Cohérence :
private void FixedUpdate()
{
if (_isCursorSynchronized)
{
inverse3.SetCursorPosition(transform.position);
}
}
L'utilisation de la méthode `FixedUpdate` permet de garantir que le contrôle de position fonctionne à une fréquence d'images stable, sans être affecté par les performances de rendu graphique.
Initialisation
à Awake() Dans ce contexte, quelle que soit la configuration (main droite ou main gauche), il faut s'assurer que Balle en mouvement Sa position de départ se trouve à l'adresse Inverse3 , à portée de l'appareil :
private void Awake()
{
inverse3.Ready.AddListener(device =>
{
GetComponent<MovableObject>().SetTargetPosition(((Inverse3)device).WorkspaceCenterLocalPosition, teleport: true);
});
}
Expérience de jeu
Veuillez bien fixer l'appareil « Inverse3 » et vous assurer qu'il dispose d'un espace suffisant autour de lui. Activez le mode de lecture (Play Mode) et approchez le curseur de la « Moving Ball » :«Inverse3 »suivra alors les mouvements de la « Moving Ball ». Vous pouvez utiliser le clavier pour déplacer la « Moving Ball » afin de démontrerla capacité du curseur à suivre sa position.

Fichier source
Le scénario complet de ce tutoriel ainsi que les fichiers associés sont disponibles dans le Unity Package Manager, sous Tutoriels que l'on trouve dans l'exemple.
Il contient MovableObject Un script utilisé dans plusieurs exemples pour contrôler le déplacement d'objets du jeu à l'aide du clavier.
SpherePositionControl.cs
/*
* Copyright 2024 Haply Robotics Inc. All rights reserved.
*/
using Haply.Inverse.DeviceControllers;
using Haply.Samples.Tutorials.Utils;
using UnityEngine;
namespace Haply.Samples.Tutorials._5_SimplePositionControl
{
/// <summary>
/// Controls the Inverse3 cursor position based on the current position of this GameObject.
/// When the GameObject is within a specified distance from the cursor, it initiates synchronized control,
/// allowing the cursor to follow the GameObject's movements.
/// </summary>
[RequireComponent(typeof(MovableObject))]
public class SpherePositionControl : MonoBehaviour
{
public Inverse3Controller inverse3;
[Tooltip("Minimum distance required to initiate synchronized control between this GameObject and the Inverse3 cursor.")]
[Range(0, 1)]
public float minSyncDistance = 0.05f;
private bool _isCursorSynchronized;
private void Awake()
{
// Ensure inverse3 is set, finding it in the scene if necessary.
inverse3 ??= FindFirstObjectByType<Inverse3Controller>();
// When inverse3 is ready, so the handedness is defined
inverse3.Ready.AddListener((device, args) =>
{
// Teleport the sphere to its workspace center to ensure it can be reached,
// regardless of whether the device is left or right-handed. This ensures the GameObject starts in a
// position that is accessible by the Inverse3 device.
GetComponent<MovableObject>().SetTargetPosition(device.WorkspaceCenterLocalPosition, teleport:true);
});
}
private void OnDisable()
{
// Ensure movement synchronization is disabled when the component is disabled.
StopSynchronizeCursor();
inverse3.Release();
}
private void Update()
{
if (!inverse3.IsReady)
{
return;
}
// Calculate the distance between the Inverse3 position and this object's position.
var distance = Vector3.Distance(inverse3.CursorPosition, transform.position);
// Enable synchronized movement if within the minimum sync distance and not already synced.
if (!_isCursorSynchronized && distance <= minSyncDistance)
{
StartSynchronizeCursor();
}
// Disable synchronized movement if outside the minimum sync distance and currently synced.
else if (_isCursorSynchronized && distance > minSyncDistance)
{
StopSynchronizeCursor();
}
}
private void FixedUpdate()
{
if (_isCursorSynchronized)
{
// If in sync, set the Inverse3 cursor position to this object's position.
inverse3.SetCursorPosition(transform.position);
}
else
{
inverse3.ProbeCursorPosition(true);
}
}
private void StartSynchronizeCursor()
{
// Get the current cursor position.
var cursorPosition = inverse3.Cursor.transform.position;
// Teleport this object to the cursor position to avoid a sudden jump when position control starts.
GetComponent<MovableObject>().SetTargetPosition(cursorPosition, teleport:true);
// Start synchronizing the movement of this object with the cursor.
_isCursorSynchronized = true;
}
private void StopSynchronizeCursor()
{
// Stop synchronizing the movement.
_isCursorSynchronized = !inverse3.Release();
}
}
}