跳转至主要内容

关于力和位置的基础教程

本指南通过一个简单的示例,演示了如何应用力以及如何可视化Inverse3 光标的运动。 最终,Inverse3 将模拟出一种感觉,即它仿佛被一根虚拟橡皮筋绑在初始位置,同时一个球形的GameObject会显示光标的位置。

引言​

《入门指南》介绍了该对象 Inverse3 及其工作原理,并介绍了产生恒定力的方法。 我们的目标是模拟光标上的橡皮筋效应。橡皮筋的行为与弹簧类似,即其作用力既受刚度影响,也受两端点之间距离的影响。 因此,我们要开发一个函数,根据给定的位置和刚度,计算出一种能够抵消光标远离原点运动的力。

场景构图​

首先,通过菜单“GameObjects >Haply”创建一个触觉 rig(单手)。

力与位置组件​

选择该 GameObject 触觉起源 完成,请插入一个名为 ForceAndPosition.cs 添加并补充该类 ForceAndPosition 关于以下代码:

[SerializeField]
private Inverse3 inverse3 = null;

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

private void OnDeviceStateChanged(object sender, Inverse3EventArgs args)
{
var inverse3 = args.DeviceController;

// Calculate the force.
var force = (inverse3.WorkspaceCenterLocalPosition - inverse3.CursorLocalPosition) * stiffness;

// Apply the force to the cursor.
inverse3.SetCursorLocalForce(force);
}

本节将刚度设定为100牛顿每米(N/m),从而模拟出一个相对较软的弹簧。 此外,还将 inverse3.WorkspaceCenterLocalPosition 引入了一项属性,该属性返回工作区域的中心点。 该方法通过将光标位置从工作区域中心点的位置中减去,然后将结果乘以刚度来计算力。 最后,利用 inverse3.SetCursorLocalForce 应用于光标。

集成回调函数 OnDeviceStateChanged 在方法中 OnEnable und OnDisable,正如在 入门指南 描述:

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

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

游戏玩法​

请长按Inverse3 光标,激活“播放模式”,然后尝试移动设备。您会发现,移动光标时会产生一股力。 光标离其初始位置越远,这种力就越明显。

光标移动

源文件​

本示例中使用的最终场景及所有相关文件,均可从 Unity 的“包管理器”中的“示例教程”中导入。

ForceAndPosition.cs​

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

using Haply.Inverse.DeviceControllers;
using Haply.Inverse.DeviceData;
using UnityEngine;

namespace Haply.Samples.Tutorials._1_ForceAndPosition
{
/// <summary>
/// Demonstrates the application of force to maintain the cursor at its center position.
/// </summary>
public class ForceAndPosition : MonoBehaviour
{
public Inverse3Controller inverse3;

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

private void Awake()
{
inverse3 ??= FindObjectOfType<Inverse3Controller>();
}

/// <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;
inverse3.Release();
}

/// <summary>
/// Event handler that calculates and send the force to the device when the cursor's position changes.
/// </summary>
/// <param name="sender">The Inverse3 data object.</param>
/// <param name="args">The event arguments containing the device data.</param>
private void OnDeviceStateChanged(object sender, Inverse3EventArgs args)
{
var inverse3 = args.DeviceController;

// Calculate the force.
var force = (inverse3.WorkspaceCenterLocalPosition - inverse3.CursorLocalPosition) * stiffness;

// Apply the force to the cursor.
inverse3.SetCursorLocalForce(force);
}
}
}