VerseGripの位置制御に関するチュートリアル
このチュートリアルでは、VerseGripの回転を利用して、Inverse3 搭載デバイスのカーソル位置を直接制御する方法を解説します。これにより、高頻度での更新を行う際にUnityのメインスレッドをバイパスすることができます。
はじめに
前述の方法とは異なり、 スタートガイド, 標準のリフレッシュレート(60Hz)で動作するこのチュートリアルでは、VerseGripデバイスの回転に応じて、Inverse3 のカーソル位置をより高い周波数(1~4kHz)で動的に調整することを目的としています。
これは、イベントを活用することで実現されます。 DeviceStateChanged、ハプティックスレッドによって引き起こされた。
シーンの設定
まず、「Haptic Rig」を作成します。『スタートガイド』に記載されている手順に従い、「GameObject」>「Haply 」>「Haptic Rig (one hand)」を選択してください。
コンポーネント「VerseGripPositionControl」
「」という名前の新しい C# スクリプトを作成します。 VerseGripPositionControl.cs そして、それをゲーム内のオブジェクトに紐付けます ハプティック・オリジン.
クラス内で以下のプロパティを定義してください VerseGripPositionControl :
public Inverse3 inverse3;
public VerseGrip verseGrip;
[Range(0, 1)]
public float speed = 0.5f;
[Range(0, 0.2f)]
public float movementLimitRadius = 0.2f;
private Vector3 _targetPosition;
- inverse3 : インスペクタで定義されたInverse3 というデバイスへの参照。
- verseGrip:カーソルの制御に使用されるVerseGripデバイスを指す。
- 速度:カーソルの移動速度。
- movementLimitRadius:カーソルが初期位置から移動できる最大距離。
- _targetPosition:カーソルが移動する先のターゲット位置。
「アウェイク・メソッド」
この方法において Awake, イベントを登録してください Ready Inverse3 のワークスペースの中心に基づいて、カーソルの目標位置を初期設定するには:
private void Awake()
{
inverse3.Ready.AddListener((inverse3Controller, args) =>
{
_targetPosition = inverse3Controller.WorkspaceCenterLocalPosition;
});
}
デバイスの準備が整うまでは、左右の区別がまだ確定していないため、ワークスペースの中央は使用できません。
メソッドを実装してください OnDeviceStateChanged VerseGripの回転とボタンの入力に基づいて、カーソルの目標位置を計算するには:
private void OnDeviceStateChanged(object sender, VerseGripEventArgs args)
{
var verseGrip = args.DeviceController;
// Calculate the direction based on the VerseGrip's rotation
var direction = verseGrip.Orientation * Vector3.forward;
// Check if the VerseGrip button is pressed down
if (verseGrip.GetButtonDown())
{
// Initialize target position
_targetPosition = inverse3.CursorLocalPosition;
}
// Check if the VerseGrip button is being held down
if (verseGrip.GetButton())
{
// Move the target position toward the grip direction
_targetPosition += direction * (0.0001f * speed);
// Clamp the target position within the movement limit radius
var workspaceCenter = inverse3.WorkspaceCenterLocalPosition;
_targetPosition = Vector3.ClampMagnitude(_targetPosition - workspaceCenter, movementLimitRadius)
+ workspaceCenter;
}
// Move cursor to new position
inverse3.SetCursorLocalPosition(_targetPosition);
}
イベントの登録と登録解除 DeviceStateChanged dans OnEnable et OnDisable.
/// Subscribes to the DeviceStateChanged event.
private void OnEnable()
{
verseGrip.DeviceStateChanged += OnDeviceStateChanged;
}
/// Unsubscribes from the DeviceStateChanged event.
private void OnDisable()
{
verseGrip.DeviceStateChanged -= OnDeviceStateChanged;
}
進行
- Inverse3 本体を固定し、動作に必要な十分なスペースが確保されていることを確認してください。
- 「プレイモード」を有効にし、カーソルをInverse3 に合わせ、そのままにしておきます。
- VerseGripを回転させて、Unityのシーン内でカーソルの動きを確認してください。この動きは、VerseGripの向きと直接連動しています。
- VerseGripのボタンを押すと、Inverse3 のスライダーがVerseGripの回転方向に沿って移動し、リアルタイムでの制御が示されます。

この図は、わかりやすくするために前軸が強調表示されたカーソルモデルを示しています。 カーソルモデルのカスタマイズに関する詳細については、カーソルに関するドキュメントを参照してください。
ソースファイル
このサンプルで使用されている最終シーンおよび関連するすべてのファイルは、Unityのパッケージマネージャーにある「Tutorials」サンプルからインポートできます。
VerseGripPositionControl.cs
/*
* Copyright 2024 Haply Robotics Inc. All rights reserved.
*/
using Haply.Inverse.DeviceControllers;
using Haply.Inverse.DeviceData;
using UnityEngine;
namespace Haply.Samples.Tutorials._6_VerseGripPositionControl
{
/// <summary>
/// Demonstrates how to control the device cursor position using the VerseGrip.
/// </summary>
public class VerseGripPositionControl : MonoBehaviour
{
public Inverse3Controller inverse3;
public VerseGripController verseGrip;
[Tooltip("Cursor moving speed")]
[Range(0, 1)]
public float speed = 0.5f;
[Tooltip("Maximum radius for cursor movement")]
[Range(0, 0.1f)]
public float movementLimitRadius = 0.075f;
private Vector3 _targetPosition; // Target position for the cursor
private void Awake()
{
inverse3.Ready.AddListener((inverse3Controller, args) =>
{
_targetPosition = inverse3Controller.WorkspaceCenterLocalPosition;
});
}
/// <summary>
/// Subscribes to the DeviceStateChanged event.
/// </summary>
private void OnEnable()
{
verseGrip.DeviceStateChanged += OnDeviceStateChanged;
}
/// <summary>
/// Unsubscribes from the DeviceStateChanged event.
/// </summary>
private void OnDisable()
{
verseGrip.DeviceStateChanged -= OnDeviceStateChanged;
inverse3.Release();
}
private void OnDeviceStateChanged(object sender, VerseGripEventArgs args)
{
var verseGrip = args.DeviceController;
// Calculate the direction based on the VerseGrip's rotation
var direction = verseGrip.Orientation * Vector3.forward;
// Check if the VerseGrip button is pressed down
if (verseGrip.GetButtonDown())
{
// Initialize target position
_targetPosition = inverse3.CursorLocalPosition;
}
// Check if the VerseGrip button is being held down
if (verseGrip.GetButton())
{
// Move the target position toward the grip direction
_targetPosition += direction * (0.0001f * speed);
// Clamp the target position within the movement limit radius
var workspaceCenter = inverse3.WorkspaceCenterLocalPosition;
_targetPosition = Vector3.ClampMagnitude(_targetPosition - workspaceCenter, movementLimitRadius)
+ workspaceCenter;
}
// Move cursor to new position
inverse3.SetCursorLocalPosition(_targetPosition);
}
}
}