Einführung in die grundlegende Kraft-Tast-Rückmeldung
In diesem Tutorial erstellen wir eine grundlegende Haptiksimulation, die sowohl Steifigkeit als auch Dämpfung berücksichtigt, um die physikalischen Eigenschaften des Kontakts mit statischen Objekten wie Kugeln nachzubilden. Am Ende dieses Tutorials verfügen Sie über eine Simulation, die die Anwesenheit einer Kugel wahrnimmt und deren Steifigkeits- und Dämpfungseigenschaften entsprechend den unterschiedlichen haptischen Erfahrungen anpassen kann.
Einleitung
Das zentrale Ziel dieses Tutorials ist die Entwicklung einer Funktion zur Berechnung der Kräfte, die durch den Kontaktmit einer Kugelentstehen,die sowohl Steifigkeit als auch Dämpfung aufweist. Die Steifigkeit wirkt in diesem Zusammenhang wie eine Feder: Je stärker sie zusammengedrückt wird, desto größer ist die Kraft, die sie erzeugt. Die Dämpfung hingegen stellt den Widerstand gegen die Bewegung des Objekts dar: Je schneller es bewegt wird, desto größer ist der Widerstand.
Einrichtung der Szene
EinführungsleitfadenRichten Sie das Haptic Rig wie dort beschrieben ein. Dabei gilt:Haptischer Ursprung Position, Drehung und Skalierung betragen jeweils (0, 0, 0)、(1, 1, 1) Bitte stellen Sie sicher, dass dies eingestellt ist.
Als Nächstes mit den folgenden Eigenschaften Sphere Erstellt eine Kugel mit dem Namen .
- Position:
(0, 0, -0.1)(ca. 10 cm vor dem Gerät) - Maßstab:
(0.2, 0.2, 0.2)(entspricht einer Kugel mit einem Durchmesser von 20 cm)
Skript für Kraft-Feedback
Sphäre Zu einem GameObject,SphereForceFeedback.cs Fügen Sie ein neues C#-Skript mit diesem Namen hinzu.
Dieses Skript berechnet die Kraft, die bei Kontakt mit einer Kugel auf den Cursor „ Inverse3 “ wirkt, unter Berücksichtigung sowohl der Steifigkeit als auch der Dämpfung.
Initialisieren Sie das Skript mit den folgenden Eigenschaften:
[SerializeField]
private Inverse3 inverse3;
[Range(0, 800)]
public float stiffness = 300f;
[Range(0, 3)]
public float damping = 1f;
private Vector3 _ballPosition;
private float _ballRadius;
private float _cursorRadius;
Die Berechnung der Kräfte muss nur dann erfolgen, wenn der Cursor in die Kugel eindringt. Dadurch wird das Gefühl der Berührung eines physikalischen Objekts mit definierter Steifigkeit und Dämpfung nachgebildet.
ForceCalculation Diese Aufgabe übernimmt die Methode, die sowohl die Position als auch die Geschwindigkeit des Cursors berücksichtigt:
private Vector3 ForceCalculation(Vector3 cursorPosition, Vector3 cursorVelocity, float cursorRadius,
Vector3 otherPosition, float otherRadius)
{
var force = Vector3.zero;
var distanceVector = cursorPosition - otherPosition;
var distance = distanceVector.magnitude;
var penetration = otherRadius + cursorRadius - distance;
if (penetration > 0)
{
// Normalize the distance vector to get the direction of the force
var normal = distanceVector.normalized;
// Calculate the force based on penetration
force = normal * penetration * stiffness;
// Apply damping based on the cursor velocity
force -= cursorVelocity * damping;
}
return force;
}
private void OnDeviceStateChanged(object sender, Inverse3EventArgs args)
{
var inverse3 = args.DeviceController;
// Calculate the ball force
var force = ForceCalculation(inverse3.CursorLocalPosition, inverse3.CursorLocalVelocity,
_cursorRadius, _ballPosition, _ballRadius);
inverse3.SetCursorLocalForce(force);
}
Awake In der Methode, um die Szenendaten festzulegen _ballPosition、_ballRadius、_cursorRadius initialisiert:
private void SaveSceneData()
{
var t = transform;
_ballPosition = t.position;
_ballRadius = t.lossyScale.x / 2f;
_cursorRadius = inverse3.Cursor.Radius;
}
private void Awake()
{
SaveSceneData();
}
OnEnable Methoden und OnDisable jeweils in der Methode OnDeviceStateChanged Registrieren und deaktivieren Sie Callbacks und verarbeiten Sie das haptische Feedback während der Interaktion ordnungsgemäß:
protected void OnEnable()
{
inverse3.DeviceStateChanged += OnDeviceStateChanged;
}
protected void OnDisable()
{
inverse3.DeviceStateChanged -= OnDeviceStateChanged;
}
Das Spielerlebnis
Inverse3 Halten Sie den Cursor gedrückt, wechseln Sie in den Play-Modus und berühren Sie die Kugel. Sie können die Präsenz der Kugel wahrnehmen und ihre Steifigkeit sowie ihre Dämpfungseigenschaften über den Inspector von Unity anpassen. Auf diese Weise erhalten Sie ein realistisches Gefühl für die Interaktion mit virtuellen Objekten.

Quelldatei
Die vollständige Szene dieses Beispiels sowie alle zugehörigen Dateien können über den Unity-Paketmanager aus den „Tutorials“-Beispielen importiert werden.
SphereForceFeedback.cs
/*
* Copyright 2024 Haply Robotics Inc. All rights reserved.
*/
using Haply.Inverse.DeviceControllers;
using Haply.Inverse.DeviceData;
using UnityEngine;
namespace Haply.Samples.Tutorials._2_BasicForceFeedback
{
public class SphereForceFeedback : MonoBehaviour
{
public Inverse3Controller inverse3;
[Range(0, 800)]
// Stiffness of the force feedback.
public float stiffness = 300f;
[Range(0, 3)]
public float damping = 1f;
private Vector3 _ballPosition;
private float _ballRadius;
private float _cursorRadius;
/// <summary>
/// Stores the cursor and sphere transform data for access by the haptic thread.
/// </summary>
private void SaveSceneData()
{
var t = transform;
_ballPosition = t.position;
_ballRadius = t.lossyScale.x / 2f;
_cursorRadius = inverse3.Cursor.Radius;
}
/// <summary>
/// Saves the initial scene data cache.
/// </summary>
private void Awake()
{
inverse3 ??= FindObjectOfType<Inverse3Controller>();
inverse3.Ready.AddListener((device, args) => SaveSceneData());
}
/// <summary>
/// Subscribes to the DeviceStateChanged event.
/// </summary>
private void OnEnable()
{
inverse3.DeviceStateChanged += OnDeviceStateChanged;
}
/// <summary>
/// Unsubscribes from the DeviceStateChanged event.
/// </summary>
private void OnDisable()
{
inverse3.DeviceStateChanged -= OnDeviceStateChanged;
inverse3.Release();
}
/// <summary>
/// Calculates the force based on the cursor's position and another sphere position.
/// </summary>
/// <param name="cursorPosition">The position of the cursor.</param>
/// <param name="cursorVelocity">The velocity of the cursor.</param>
/// <param name="cursorRadius">The radius of the cursor.</param>
/// <param name="otherPosition">The position of the other sphere (e.g., ball).</param>
/// <param name="otherRadius">The radius of the other sphere.</param>
/// <returns>The calculated force vector.</returns>
private Vector3 ForceCalculation(Vector3 cursorPosition, Vector3 cursorVelocity, float cursorRadius,
Vector3 otherPosition, float otherRadius)
{
var force = Vector3.zero;
var distanceVector = cursorPosition - otherPosition;
var distance = distanceVector.magnitude;
var penetration = otherRadius + cursorRadius - distance;
if (penetration > 0)
{
// Normalize the distance vector to get the direction of the force
var normal = distanceVector.normalized;
// Calculate the force based on penetration
force = normal * penetration * stiffness;
// Apply damping based on the cursor velocity
force -= cursorVelocity * damping;
}
return force;
}
/// <summary>
/// Event handler that calculates and send the force to the device when the cursor's position changes.
/// </summary>
/// <param name="sender">The Inverse3 data object.</param>
/// <param name="args">The event arguments containing the device data.</param>
private void OnDeviceStateChanged(object sender, Inverse3EventArgs args)
{
var inverse3 = args.DeviceController;
// Calculate the ball force
var force = ForceCalculation(inverse3.CursorLocalPosition, inverse3.CursorLocalVelocity,
_cursorRadius, _ballPosition, _ballRadius);
inverse3.SetCursorLocalForce(force);
}
}
}