Aller au contenu principal

Tutoriel simple sur le contrôle de position

Ce tutoriel explique comment contrôler la position du curseur d'un appareil Inverse3 à l'aide d'un GameObject dynamique dans une scène Unity, en s'appuyant sur les concepts présentés dans le guide « Premiers pas ».

Introduction​

L'appareil « Inverse3 » prend en charge deux modes de commande : Commande de force et Commande de position. Alors que le contrôle de force ajuste la force en fonction de la position du curseur, le contrôle de position commande directement la position du curseur. Ce tutoriel utilise la configuration de scène issue du Tutoriel sur le retour de force dans une scène dynamique et se concentre sur l'utilisation de CursorSetPosition innerhalb der Methode FixedUpdate, afin que le curseur de l'appareil suive un GameObject en mouvement.

Mise en place des scènes​

Commencez par configurer la scène à partir du Tutoriel sur le retour de force dans une scène dynamique, qui ont un Dispositif haptique et un GameObject Balle en mouvement qui comprend, grâce au composant MovableObject est commandé.

Implémentation du composant SpherePositionControl​

Remplacez le composant SphereForceFeedback est un GameObject Balle en mouvement grâce à un nouveau script C# intitulé SpherePositionControl.cs. Définissez dans la classe SpherePositionControl les caractéristiques suivantes :

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: distance minimale à partir de laquelle la synchronisation des curseurs est lancée.
  • _isCursorSynchronized: indicateur précisant si le déplacement du curseur est synchronisé avec celui de la « Moving Ball ».

Logique de synchronisation​

Mettez en place des méthodes permettant de lancer et d'arrêter la synchronisation du curseur en fonction de la proximité par rapport à la balle en mouvement:

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

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

C'est ici que MovableObject.SetTargetPosition(position, teleport:true) utilisé, ce qui fait que le MovingBall est téléporté à la position du curseur.

Méthodes Update et FixedUpdate​

Dans la méthode, passez à Update La synchronisation du curseur dépend de la distance entre le curseur et Balle en mouvement euh :

private void Update()
{
var distance = Vector3.Distance(inverse3.CursorPosition, transform.position);
if (!_isCursorSynchronized && distance <= minSyncDistance)
{
StartSynchronizeCursor();
}
else if (_isCursorSynchronized && distance > minSyncDistance)
{
StopSynchronizeCursor();
}
}

Mettez à jour dans FixedUpdate positionner le curseur de manière à ce qu'il corresponde à la position du Balle en mouvement correspond, à condition que la synchronisation soit 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, quelle que soit la puissance du rendu graphique.

Initialisation​

Réglez sur Awake() s'assurer que le Balle en mouvement qui commence dans une position accessible à l'appareil « Inverse3 », quelle que soit la main dominante de l'utilisateur :

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

Expérience de jeu​

Fixez l'appareil « Inverse3 » et veillez à disposer de suffisamment d'espace. Lorsque vous activez le mode « Play » et que vous approchez le curseur de la « Moving Ball », l'appareil « Inverse3 » suit les mouvements de cette dernière. La « Moving Ball » peut être déplacée à l'aide du clavier, ce qui permet de démontrer la capacité du curseur à suivre sa position.

contrôle de position simple

Fichiers source​

Vous trouverez la scène complète et les fichiers associés à ce tutoriel dans l'exemple Tutoriels C'est le gestionnaire de paquets de Unity. Il comprend le script MovableObject, qui est utilisé dans plusieurs exemples pour contrôler le déplacement des GameObjects à 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();
}
}
}