跳至主要内容
版本:最新

基本力反馈教程

物理对象有两种属性,即刚度和阻尼,这两种属性决定了它们的感觉。本教程 将介绍触觉模拟,其中包括与水平面接触时产生的刚度和阻尼。 水平面产生的刚度和阻尼。模拟完成后,您将有机会感受 "地板",并调整其刚度和阻尼特性。 调整其刚度和阻尼特性。

导言

本教程的主要挑战是开发一个函数,计算与具有刚度和阻尼的地平面接触时产生的力。 与具有刚度阻尼的地平面接触所产生的力。

物体刚度的作用就像弹簧,压缩得越多,力就越大。与此相反、 阻尼是物体对运动的阻力。例如,水没有硬度,但它有 阻尼,因此在缓慢接触时不会产生阻力,而在快速移动时则会产生很大的阻力。 快速移动时会产生很大的阻力。

场景设置

如《快速入门指南》所示,首先创建一个HapticThread和一个球形光标可视化器。 指南。接着,创建一个平面(Plane),将其命名为 "地面"(Ground),并将其 y 位置设置为 -0.4。创建新的 C# 脚本 创建名为 GroundForce.cs 的新 C# 脚本,将其添加到与 HapticThread 相同的 GameObject 中,并在 GroundForce 类中添加以下属性 属性

[Range(0, 800)]
public float stiffness = 600f;
[Range(0, 3)]
public float damping = 1;

public Transform ground;
private float m_groundHeight;
private float m_cursorRadius;

当远离平面时,Inverse3 不应产生任何力。只有当 光标接触平面表面时才会产生力,即光标穿透平面。穿透深度 计算不仅取决于平面位置,还取决于光标的可视化半径。在这种情况下 在这种情况下,从逆 3 位置减去光标半径就足以正确显示光标的相对位置。 光标的相对位置。

当光标接触平面时,产生的力取决于光标的位置和速度、 均由 Inverse3 提供(请参阅使用 Inverse3 进行开发),这意味着 力计算方法是

private Vector3 ForceCalculation ( in Vector3 position, in Vector3 velocity )
{
var force = Vector3.zero;

// Bottom of the sphere
var contactPoint = position.y - m_cursorRadius;

var penetration = m_groundHeight - contactPoint;
if ( penetration > 0 )
{
force.y = penetration * stiffness - velocity.y * damping;
}

return force;
}

接下来,更新 Awake 方法来:分配 m_groundHeightm_cursorRadius触觉线程, 并启动它。

private void Awake ()
{
m_groundHeight = ground.transform.position.y;

var hapticThread = GetComponent<HapticThread>();
m_cursorRadius = hapticThread.avatar.lossyScale.y / 2;

hapticThread.onInitialized.AddListener(() => hapticThread.Run( ForceCalculation ));
}

最后,打开GroundForce脚本的检查器窗口,将平面分配到 相应字段。启动游戏模式并触摸地平面。尝试不同的刚度阻尼值,看看两者产生的感觉有何不同。

光标落地

源文件

本示例使用的最终场景和所有相关文件可从 Unity 软件包管理器中的 "基本力反馈和工作区控制"示例导入。

using Haply.HardwareAPI.Unity;
using UnityEngine;

public class GroundForce : MonoBehaviour
{
[Range(0, 800)]
public float stiffness = 600f;
[Range(0, 3)]
public float damping = 1;

public Transform ground;

private float m_groundHeight;
private float m_cursorRadius;

private void Start ()
{
var hapticThread = GetComponent<HapticThread>();

m_groundHeight = ground.transform.position.y;
m_cursorRadius = hapticThread.avatar.lossyScale.y / 2;

hapticThread.onInitialized.AddListener(() => hapticThread.Run( ForceCalculation ));
}

private Vector3 ForceCalculation ( in Vector3 position, in Vector3 velocity )
{
var force = Vector3.zero;

var contactPoint = position.y - m_cursorRadius;
var penetration = m_groundHeight - contactPoint;
if ( penetration > 0 )
{
force.y = penetration * stiffness;
force.y -= velocity.y * damping;
}

return force;
}
}