Tutoriel sur le contrôle de position simple
Ce tutoriel explique comment contrôler la position du curseur d'un appareil Inverse3 à l'aide d'un objet de jeu dynamique dans une scène Unity, en s'appuyant sur les concepts présentés dans le Guide de démarrage.
Introduction
L'appareil Inverse3 prend en charge deux modes de commande : Contrôle de la force et Contrôle de position.
Alors que le premier ajuste la force en fonction de la position du curseur, le second modifie directement la position du curseur.
Ce tutoriel, qui reprend la configuration de scène du Tutoriel sur le retour de force dans une scène dynamique, se concentre sur l'utilisation de CursorSetPosition dans la méthode FixedUpdate afin que le curseur de la console suive un objet du jeu en mouvement.
Configuration de la scène
Commencez par la configuration de scène décrite dans le Tutoriel sur le retour de force dans une scène dynamique, qui comprend un Dispositif haptique et un objet de jeu Balle en mouvement contrôlé par le composant MovableObject.
Implémentation du composant SpherePositionControl
Remplacez le composant SphereForceFeedback de l'objet de jeu Balle en mouvement par un nouveau script C# intitulé SpherePositionControl.cs.
Définissez les propriétés suivantes dans la classe SpherePositionControl :
public Inverse3 inverse3;
public float minSyncDistance = 0.05f;
private bool _isCursorSynchronized;
- inverse3 : référence au composant de l'appareil Inverse3, défini dans l'inspecteur.
- minSyncDistance: seuil de distance minimale pour déclencher la synchronisation du curseur.
- _isCursorSynchronized: indicateur précisant si le mouvement du curseur est synchronisé avec la « Moving Ball ».
Logique de synchronisation
Mettez en place des méthodes permettant de démarrer et d'arrêter la synchronisation du curseur en fonction de la proximité de 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();
}
Ici, nous utilisons
MovableObject.SetTargetPosition(position, teleport:true), qui téléporte le MovingBall à la position du curseur.
Méthodes Update et FixedUpdate
Dans la méthode Update, activez ou désactivez la synchronisation du curseur en fonction de la distance entre le curseur et le Balle en mouvement :
private void Update()
{
var distance = Vector3.Distance(inverse3.CursorPosition, transform.position);
if (!_isCursorSynchronized && distance <= minSyncDistance)
{
StartSynchronizeCursor();
}
else if (_isCursorSynchronized && distance > minSyncDistance)
{
StopSynchronizeCursor();
}
}
Dans FixedUpdate, mettez à jour la position du curseur pour qu'elle corresponde à celle du Balle en mouvement si la synchronisation est activée :
private void FixedUpdate()
{
if (_isCursorSynchronized)
{
inverse3.SetCursorPosition(transform.position);
}
}
Utilisez la méthode FixedUpdate pour que le contrôle de position fonctionne à une fréquence d'images stable, quelles que soient les performances du rendu graphique.
Initialisation
Dans Awake(), assurez-vous que le Balle en mouvement commence à une position accessible par l'appareil Inverse3, quelle que soit sa latéralité :
private void Awake()
{
inverse3.Ready.AddListener(device =>
{
GetComponent<MovableObject>().SetTargetPosition(((Inverse3)device).WorkspaceCenterLocalPosition, teleport: true);
});
}
Expérience de jeu
Fixez l'appareil Inverse3 et assurez-vous qu'il dispose d'un espace suffisant. En activant le mode « Play » et en approchant le curseur de la « Moving Ball », l'appareil Inverse3 suivra les mouvements de la « Moving Ball ». Les saisies au clavier peuvent servir à déplacer la « Moving Ball », ce qui démontre la capacité du curseur à suivre sa position.

Fichiers sources
La scène complète et les fichiers associés à ce tutoriel se trouvent dans l'exemple Tutoriels du gestionnaire de paquets de Unity.
Cela comprend le script MovableObject, qui est utilisé dans plusieurs exemples pour contrôler le déplacement des objets du jeu à l'aide des commandes 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();
}
}
}