Skip to main content
Version : 2.1.1

Tutoriel de contrôle de position simple

Ce tutoriel montre comment contrôler la position du curseur d'un dispositif Inverse3 avec un objet de jeu dynamique dans une scène Unity, en s'appuyant sur les concepts introduits dans le Guide de démarrage rapide.

Introduction

Le dispositif Inverse3 prend en charge deux modes de contrôle : Contrôle des forces et Contrôle de position. Alors que le premier ajuste la force en fonction de la position du curseur, le second manipule directement la position du curseur. Ce tutoriel, qui s'appuie sur la configuration de la scène de Retour d'effort dans une scène dynamique TutorielL'objectif est d'employer CursorSetPosition au sein de la FixedUpdate pour permettre au curseur de l'appareil de suivre un objet de jeu en mouvement.

Configuration de la scène

Commencez par la configuration de la scène décrite dans le Retour d'effort dans une scène dynamique Tutorielqui comprend un Dispositif haptique et un Balle en mouvement objet de jeu contrôlé par le MovableObject de la composante.

Mise en œuvre du composant SpherePositionControl

Remplacer le SphereForceFeedback sur la page d'accueil de la Balle en mouvement GameObject avec un nouveau script C# nommé SpherePositionControl.cs. Définir les propriétés suivantes dans le SpherePositionControl classe :

public Inverse3 inverse3;
public float minSyncDistance = 0.05f;
private bool _isCursorSynchronized;
  • inverse3: Référence au composant Inverse3, définie via l'inspecteur.
  • minSyncDistance: Seuil de distance minimale pour déclencher la synchronisation du curseur.
  • isCursorSynchronized: Drapeau indiquant si le mouvement du curseur est synchronisé avec la boule en mouvement.

Logique de synchronisation

Mettre en œuvre des méthodes pour démarrer et arrêter la synchronisation du curseur en fonction de la proximité de la boule mobile :

private void StartSynchronizeCursor()
{
var cursorPosition = inverse3.Cursor.transform.position;
GetComponent<MovableObject>().SetTargetPosition(cursorPosition, teleport: true);
_isCursorSynchronized = true;
}

private void StopSynchronizeCursor()
{
_isCursorSynchronized = !inverse3.Release();
}

Nous utilisons ici le MovableObject.SetTargetPosition(position, teleport:true) qui téléportent le MovingBall à la position du curseur.

Méthodes Update et FixedUpdate

Dans le cadre de la Update méthode, basculer la synchronisation du curseur sur la base 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();
}
}

En FixedUpdate, met à jour la position du curseur pour qu'elle corresponde à celle du Balle en mouvement si la synchronisation est active :

private void FixedUpdate()
{
if (_isCursorSynchronized)
{
inverse3.CursorSetPosition(transform.position);
}
}

Utilisez la méthode FixedUpdate pour vous assurer que le contrôle de la position fonctionne à une fréquence d'images stable, indépendamment des performances du rendu graphique.

Initialisation

En Awake(), assurez-vous que le Balle en mouvement commence dans une position accessible par le dispositif Inverse3, quelle que soit sa main :

private void Awake()
{
inverse3.DeviceOpened.AddListener(device =>
{
GetComponent<MovableObject>().SetTargetPosition(((Inverse3)device).WorkspaceCenter, teleport: true);
});
}

Expérience de jeu

Fixez le dispositif Inverse3 et assurez-vous qu'il dispose d'un espace suffisant. En activant le mode Play et en approchant la Moving Ball avec le curseur, l'Inverse3 suivra les mouvements de la Moving Ball. Les entrées au clavier peuvent être utilisées pour déplacer la balle mobile, démontrant ainsi la capacité du curseur à suivre sa position.

contrôle de position simple

Fichiers sources

La scène complète et les fichiers associés de ce tutoriel se trouvent dans le fichier Tutoriels dans le gestionnaire de paquets Unity. Cet exemple comprend les éléments suivants MovableObject qui est utilisé dans plusieurs exemples pour contrôler le mouvement des objets du jeu par l'intermédiaire des entrées clavier.

SpherePositionControl.cs

/*
* Copyright 2024 Haply Robotics Inc. All rights reserved.
*/

using Haply.Inverse.Unity;
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 Inverse3 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.
if (inverse3 == null)
{
inverse3 = FindObjectOfType<Inverse3>();
}

// When inverse3 is ready, so the handedness is defined
inverse3.DeviceOpened.AddListener(device =>
{
var inverse3 = (Inverse3)device;
// 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(((Inverse3)device).WorkspaceCenter, teleport:true);
});
}

private void OnDisable()
{
// Ensure movement synchronization is disabled when the component is disabled.
StopSynchronizeCursor();
}

private void Update()
{
// 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.CursorSetPosition(transform.position);
}
}

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();
}
}
}