VerseGrip 位置控制教程
本教程演示了如何使用 VerseGrip 的旋转功能直接控制 Inverse3 设备光标的位置,从而绕过 Unity 主线程进行高频更新。
导言
与 快速入门指南本教程的目的是根据 VerseGrip 设备以更高频率(1~4kHz)的旋转动态调整 Inverse3 光标的位置。
这是通过利用 DeviceStateChanged
事件,由触觉线程触发。
场景设置
首先创建触觉装配:GameObject > Haply > Haptic Rig(单手),详见《快速入门指南》。
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 设备的引用。
- speed:光标移动的速度。
- movementLimitRadius:光标从初始位置移动的最大距离。
- _targetPosition(目标位置):光标移动的目标位置。
实施 OnDeviceStateChanged
方法,根据 VerseGrip 的旋转和按钮输入计算光标的目标位置:
private void OnDeviceStateChanged(VerseGrip grip)
{
// Calculate the direction based on the VerseGrip's rotation
var direction = grip.LocalRotation * Vector3.forward;
// Check if the VerseGrip button is pressed down
if (grip.GetButtonDown())
{
// Initialize target position
_targetPosition = inverse3.LocalPosition;
}
// Check if the VerseGrip button is being held down
if (grip.GetButton())
{
// Move the target position toward the grip direction
_targetPosition += direction * (0.0025f * speed);
// Clamp the target position within the movement limit radius
var workspaceCenter = inverse3.WorkspaceCenter;
_targetPosition = Vector3.ClampMagnitude(_targetPosition - workspaceCenter, movementLimitRadius)
+ workspaceCenter;
// Move cursor to new position
inverse3.CursorSetLocalPosition(_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;
}
可选: 在 Update
方法,让用户可以重置 Inverse3 的力值。
private void Update()
{
// Check for space key to disable position control
if (Input.GetKeyDown(KeyCode.Space))
{
// Reset cursor force to disable position control
inverse3.TryResetForce();
}
}
游戏玩法
- 固定好 Inverse3 设备,确保有足够的活动空间。
- 进入播放模式并按住反向 3 光标。
- 旋转 VerseGrip,观察光标在 Unity 场景中的移动,这与 VerseGrip 的方向直接对应。
- 按下 VerseGrip 的按钮,Inverse3 的光标就会沿着 VerseGrip 的旋转方向移动,从而实现实时控制。
图片说明了光标模型,为清晰起见,突出显示了其前轴。 有关自定义光标模型的更多详情,请参阅光标文档。
源文件
本示例使用的最终场景和所有相关文件都可以从 Unity 软件包管理器中的教程示例中导入。
VerseGripPositionControl.cs
/*
* Copyright 2024 Haply Robotics Inc. All rights reserved.
*/
using Haply.Inverse.Unity;
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
{
// Must be assigned in inspector
public Inverse3 inverse3;
public VerseGrip verseGrip;
[Tooltip("Cursor moving speed")]
[Range(0, 1)]
public float speed = 0.5f;
[Tooltip("Maximum radius for cursor movement")]
[Range(0, 0.2f)]
public float movementLimitRadius = 0.2f;
private Vector3 _targetPosition; // Target position for the cursor
/// <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;
}
private void Update()
{
// Check for space key to disable position control
if (Input.GetKeyDown(KeyCode.Space))
{
// Reset cursor force to disable position control
inverse3.TryResetForce();
}
}
private void OnDeviceStateChanged(VerseGrip grip)
{
// Calculate the direction based on the VerseGrip's rotation
var direction = grip.LocalRotation * Vector3.forward;
// Check if the VerseGrip button is pressed down
if (grip.GetButtonDown())
{
// Initialize target position
_targetPosition = inverse3.LocalPosition;
}
// Check if the VerseGrip button is being held down
if (grip.GetButton())
{
// Move the target position toward the grip direction
_targetPosition += direction * (0.0025f * speed);
// Clamp the target position within the movement limit radius
var workspaceCenter = inverse3.WorkspaceCenter;
_targetPosition = Vector3.ClampMagnitude(_targetPosition - workspaceCenter, movementLimitRadius)
+ workspaceCenter;
// Move cursor to new position
inverse3.CursorSetLocalPosition(_targetPosition);
}
}
}