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

基本的な力と位置のチュートリアル

このガイドでは、Inverse3のカーソルに力を加え、その動きを視覚化する簡単なデモンストレーションを紹介します。 最終的には、Inverse3がバーチャルなゴムバンドで開始位置に縛られている感覚をシミュレートし、球体のGameObjectがカーソルの位置を表示します。

はじめに

クイックスタートガイドではInverse3オブジェクトとその機能、そして一定の力を生成する方法を紹介しました。 ここでの目的は、カーソルのラバーバンド効果をシミュレートすることです。輪ゴムはバネと同じように動作し、その力は剛性と2つの端点間の距離の両方に影響されます。 したがって、位置と剛性が与えられ、カーソルが原点から離れる動きに抵抗する力を生成する関数を考案することを目的とします。

シーン設定

GameObjects > HaplyメニューからHaptic Rig(片手)を作成して開始します。

ForceAndPosition コンポーネント

を選択する。 ハプティック・オリジン という名前の新しいスクリプトを追加する。 ForceAndPosition.cs を入力し ForceAndPosition クラスに以下のコードを追加した:

[SerializeField]
private Inverse3 inverse3 = null;

[SerializeField, Range(0, 400)]
private float stiffness = 100;

private Vector3 _initialPosition = Vector3.zero;

private Vector3 ForceCalculation(in Vector3 position)
{
if (_initialPosition == Vector3.zero)
{
// Save the initial device effector position
_initialPosition = position;
}
// Return force opposing movement from the initial position
return (_initialPosition - position) * stiffness;
}

このセグメントでは、剛性を100ニュートン/メートル(N/m)に設定し、比較的柔らかいスプリングをシミュレートしています。 また _initialPositionカーソルの開始位置を表すベクトル。 このベクトルは ForceCalculation メソッドは、最初の実行時に初期位置を記録し、その後カーソルの移動に対抗する力の出力を計算する。

を組み込む。 OnDeviceStateChanged コールバックは OnEnable そして OnDisable に詳述されている。 クイックスタートガイド:

protected void OnEnable()
{
inverse3.DeviceStateChanged += OnDeviceStateChanged;
}

protected void OnDisable()
{
inverse3.DeviceStateChanged -= OnDeviceStateChanged;
}

ゲームプレイ

Inverse3カーソルをホールドし、プレイモードをアクティブにして、デバイスを操作してみる。カーソルを変位させると力が発生することがわかるだろう。 カーソルが開始位置から遠ざかれば遠ざかるほど、この力はより顕著になる。

カーソル移動

ソースファイル

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

ForceAndPosition.cs

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

using Haply.Inverse.Unity;
using UnityEngine;

namespace Haply.Samples.Tutorials._1_ForceAndPosition
{
/// <summary>
/// Demonstrates the application of force to maintain the cursor at its initial position.
/// </summary>
public class ForceAndPosition : MonoBehaviour
{
// Must be assigned in inspector
public Inverse3 inverse3;

[Range(0, 400)]
// Stiffness of the force feedback.
public float stiffness = 100;

// Stores the initial position of the cursor.
private Vector3 _initialPosition = Vector3.zero;

/// <summary>
/// Subscribes to the DeviceStateChanged event when the component is enabled.
/// </summary>
protected void OnEnable()
{
inverse3.DeviceStateChanged += OnDeviceStateChanged;
}

/// <summary>
/// Unsubscribes from the DeviceStateChanged event and reset the force when the component is disabled.
/// </summary>
protected void OnDisable()
{
inverse3.DeviceStateChanged -= OnDeviceStateChanged;
}

/// <summary>
/// Calculates the force required to maintain the cursor at its initial position.
/// </summary>
/// <param name="position">The current position of the cursor.</param>
/// <returns>The calculated force vector.</returns>
private Vector3 ForceCalculation(in Vector3 position)
{
if (_initialPosition == Vector3.zero)
{
// save the first device effector position
_initialPosition = position;
}
// return opposite force to stay at initial position
return (_initialPosition - position) * stiffness;
}

/// <summary>
/// Event handler that calculates and send the force to the device when the cursor's position changes.
/// </summary>
/// <param name="device">The Inverse3 device instance.</param>
private void OnDeviceStateChanged(Inverse3 device)
{
// Calculate the force.
var force = ForceCalculation(device.CursorLocalPosition);

// Apply the force to the cursor.
inverse3.CursorSetLocalForce(force);
}
}
} // namespace Haply.Samples.Tutorials._1_ForceAndPosition