本文へスキップ
バージョン:最新

ダイナミックシーンでのフォースフィードバック チュートリアル

ハプティックスレッドは物理スレッドよりも桁違いに高速である。 スレッドは物理スレッドよりも桁違いに高速であるため、複数の触覚更新が各スレッドの間に発生する可能性がある。 FixedUpdate() を呼び出します。これは、物理学的変化を計算するために使用されるシーンデータと、触覚フィードバックを計算するために使用されるハプティックスレッド内のデータとの間の不整合につながります。 ハプティックフィードバックを計算するために使用されるハプティックスレッドのデータとの間に矛盾が生じます。

この例では、シーンデータをハプティックループと同期させるスレッドセーフアプローチを示す。 をハプティックループと同期させるスレッドセーフなアプローチを示します。

シーン設定

  • 力とカーソルの位置で示したように、触覚スレッドと カーソルを追加する。
  • を作成する。 スフィア という ムービング・ボール に設定する。 (0, 0.15, -0.15) とその規模は (0.1, 0.1, 0.1)

ハプティック・ループ

新規追加 C#スクリプト という MovingBallForce.cs に対する ムービング・ボール ゲーム・オブジェクトを生成する。このスクリプトのソースを以下に示す。

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

プレイ・モードに入り、矢印キーを使って球体を動かし、サイズを変更する。球体の大きさと位置の変化を目で見て感じてください。

ムービングボール

ソースファイル

この例で使用する最終シーンとすべての関連ファイルは、Unityのパッケージマネージャからインポートできます。