Zum Hauptinhalt springen
Version: neueste

Kraftrückkopplung in einer dynamischen Szene Tutorial

Da der haptische Thread um eine Größenordnung schneller sein kann als der physikalische kann, können mehrere haptische Updates zwischen den einzelnen FixedUpdate() aufrufen. Dies führt zu Inkonsistenzen zwischen den Szenendaten, die zur Berechnung der physikalischen Änderungen verwendet werden, und den Daten im haptischen Thread, die zur Berechnung des haptischen Feedbacks verwendet werden.

In diesem Beispiel zeigen wir einen thread-sicheren Ansatz zur Synchronisierung von Szenendaten mit der haptischen Schleife.

Szene einrichten

  • Fügen Sie einen haptischen Faden und einen Cursor hinzu, wie in Kraft und Cursorposition gezeigt
  • Erstellen einer Sphäre genannt. Bewegter Ball und setzen Sie seine Position auf (0, 0.15, -0.15) und seine Skala auf (0.1, 0.1, 0.1)

Die haptische Schleife

Hinzufügen einer neuen C#-Skript genannt. MovingBallForce.cs zum Bewegter Ball Spielobjekt. Die Quelle für dieses Skript ist unten angegeben.

using Haply.HardwareAPI.Unity;
using UnityEngine;

public class MovingBallForce : MonoBehaviour
{
// Thread-safe scene data struct
private struct AdditionalData
{
public Vector3 ballPosition;

// cursor radius + ball radius
public float radiuses;
}

[Range(0, 800)]
public float stiffness = 600f;

// Moving/scaling speed (by pressing arrow keys)
public float speed = 0.2f;

private HapticThread m_hapticThread;

private void Awake ()
{
// Find the HapticThread object before the our first FixedUpdate() call
m_hapticThread = FindObjectOfType<HapticThread>();

// Run the haptic loop with an initial state returned by AdditionalData.
var initialState = GetAdditionalData();
m_hapticThread.onInitialized.AddListener(() => m_hapticThread.Run(ForceCalculation, initialState));
}

private void FixedUpdate ()
{
// Change the scale of the ball
if ( Input.GetKey( KeyCode.UpArrow ) )
transform.localScale += Vector3.one * (Time.fixedDeltaTime * speed);
else if ( Input.GetKey( KeyCode.DownArrow ) )
transform.localScale -= Vector3.one * (Time.fixedDeltaTime * speed);

// Move the ball
if ( Input.GetKey( KeyCode.LeftArrow ) )
transform.transform.position += Vector3.left * (Time.fixedDeltaTime * speed);
else if (Input.GetKey(KeyCode.RightArrow))
transform.transform.position += Vector3.right * (Time.fixedDeltaTime * speed);

// Update AdditionalData with the latest physics data
m_hapticThread.SetAdditionalData(GetAdditionalData());
}

// Method used by HapticThread.Run(ForceCalculation) and HapticThread.GetAdditionalData()
// to synchronize dynamic data between the unity scene and the haptic thread
private AdditionalData GetAdditionalData ()
{
AdditionalData additionalData;

additionalData.ballPosition = transform.localPosition;
additionalData.radiuses = (transform.localScale.x + m_hapticThread.avatar.localScale.x) / 2f;

return additionalData;
}

// Calculate the force to apply when the cursor touches the ball.
// This is done through additionalData to keep things thread-safe.
private Vector3 ComputeForce ( in Vector3 position, in Vector3 velocity, in AdditionalData additionalData )
{
var force = Vector3.zero;

var distance = Vector3.Distance( position, additionalData.ballPosition );

if ( distance < additionalData.radiuses )
{
var penetration = additionalData.radiuses - distance;
force = (position - additionalData.ballPosition) / distance * penetration * stiffness;
}

return force;
}
}

Gehen Sie in den Spielmodus und verwenden Sie die Pfeiltasten, um die Kugel zu bewegen und ihre Größe zu verändern. Sie sollten die Veränderungen in der Größe und Position der Kugel sehen und fühlen.

beweglicher Ball

Quelldateien

Die endgültige Szene und alle zugehörigen Dateien, die in diesem Beispiel verwendet werden, können über den Paketmanager von Unity importiert werden.