基本力和位置教程
本指南提供了一个施加力和可视化 Inverse3 光标移动的简单演示。 最后,Inverse3 将模拟被虚拟橡皮筋拴在起始位置的感觉,同时球形 GameObject 将显示光标的位置。
导言
快速入门指南》介绍了Inverse3对象、其功能以及产生恒力的方法。 我们这里的目的是模拟光标上的橡皮筋效应。橡皮筋的行为类似于弹簧,这意味着它的力受其两端点之间的刚度和距离的影响。 因此,我们的目标是设计一个函数,在给定位置和刚度的情况下,产生一个力,使光标抵制远离原点的移动。
场景设置
首先通过GameObjects ( 游戏对象 ) > Haply菜单创建一个触觉装配(单手)。
力和位置组件
选择 触觉起源 游戏对象,并添加一个名为 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 软件包管理器中的教程示例中导入。
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