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

VerseGripポジションコントロール・チュートリアル

このチュートリアルでは、VerseGripの回転を使用して、Inverse3 デバイスのカーソルの位置を直接制御し、Unityのメインスレッドをバイパスして高頻度の更新を行う方法を紹介します。

はじめに

で示した方法とは異なる。 クイックスタートガイドこのチュートリアルでは、標準的な更新頻度(60Hz)で動作するVerseGripデバイスの回転に基づいて、Inverse3 カーソルの位置をより高い頻度(1~4kHz)で動的に調整することを目的としています。 これは DeviceStateChanged イベントが発生する。

シーン設定

まず、Haptic Rigを作成します:GameObject(ゲームオブジェクト) >Haply >Haptic Rig(片手)を作成します。

VerseGripPositionControl コンポーネント

という名前の新しいC#スクリプトを作成する。 VerseGripPositionControl.cs に貼り付ける。 ハプティック・オリジン GameObject。 以下のプロパティを 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デバイスへの参照。
  • speed: カーソルの移動速度。
  • 移動限界半径:カーソルが初期位置から移動できる最大距離。
  • _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 イベント OnEnable そして 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);
}
}
}