跳至主要内容
版本:最新

动态场景中的力反馈教程

因为触觉线程的速度比物理线程快一个数量级。 线程的速度快一个数量级,因此在每个 FixedUpdate() 调用。这导致用于计算物理变化的场景数据与用于计算触觉反馈的 触觉线程中用于计算触觉反馈的数据不一致。

在此示例中,我们展示了一种线程安全方法,用于同步场景数据和触觉循环。 与触觉循环同步的线程安全方法。

场景设置

  • 力度和光标位置所示,添加触觉线程光标
  • 创建一个 球体 人称 移动球 并将其位置设置为 (0, 0.15, -0.15) 及其规模 (0.1, 0.1, 0.1)

触觉环路

添加新的 C# 脚本 人称 MovingBallForce.cs移动球 游戏对象。该脚本的源代码如下。

using Haply.HardwareAPI.Unity;
using UnityEngine;

public class MovingBallForce : MonoBehaviour
{
// Thread-safe scene data struct
private struct AdditionalData
{
public Vector3 ballPosition;

// cursor radius + ball radius
public float radiuses;
}

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

// Moving/scaling speed (by pressing arrow keys)
public float speed = 0.2f;

private HapticThread m_hapticThread;

private void Awake ()
{
// Find the HapticThread object before the our first FixedUpdate() call
m_hapticThread = FindObjectOfType<HapticThread>();

// Run the haptic loop with an initial state returned by AdditionalData.
var initialState = GetAdditionalData();
m_hapticThread.onInitialized.AddListener(() => m_hapticThread.Run(ForceCalculation, initialState));
}

private void FixedUpdate ()
{
// Change the scale of the ball
if ( Input.GetKey( KeyCode.UpArrow ) )
transform.localScale += Vector3.one * (Time.fixedDeltaTime * speed);
else if ( Input.GetKey( KeyCode.DownArrow ) )
transform.localScale -= Vector3.one * (Time.fixedDeltaTime * speed);

// Move the ball
if ( Input.GetKey( KeyCode.LeftArrow ) )
transform.transform.position += Vector3.left * (Time.fixedDeltaTime * speed);
else if (Input.GetKey(KeyCode.RightArrow))
transform.transform.position += Vector3.right * (Time.fixedDeltaTime * speed);

// Update AdditionalData with the latest physics data
m_hapticThread.SetAdditionalData(GetAdditionalData());
}

// Method used by HapticThread.Run(ForceCalculation) and HapticThread.GetAdditionalData()
// to synchronize dynamic data between the unity scene and the haptic thread
private AdditionalData GetAdditionalData ()
{
AdditionalData additionalData;

additionalData.ballPosition = transform.localPosition;
additionalData.radiuses = (transform.localScale.x + m_hapticThread.avatar.localScale.x) / 2f;

return additionalData;
}

// Calculate the force to apply when the cursor touches the ball.
// This is done through additionalData to keep things thread-safe.
private Vector3 ComputeForce ( in Vector3 position, in Vector3 velocity, in AdditionalData additionalData )
{
var force = Vector3.zero;

var distance = Vector3.Distance( position, additionalData.ballPosition );

if ( distance < additionalData.radiuses )
{
var penetration = additionalData.radiuses - distance;
force = (position - additionalData.ballPosition) / distance * penetration * stiffness;
}

return force;
}
}

进入游戏模式,使用箭头键移动球体并调整其大小。你应该能看到并感觉到球体大小和位置的变化。

动球

源文件

本示例使用的最终场景和所有相关文件都可以从 Unity 的软件包管理器中导入。