动态场景中的力反馈教程
因为触觉线程的速度比物理线程快一个数量级。
线程的速度快一个数量级,因此在每个 FixedUpdate()
调用。这导致用于计算物理变化的场景数据与用于计算触觉反馈的
触觉线程中用于计算触觉反馈的数据不一致。
在此示例中,我们展示了一种线程安全方法,用于同步场景数据和触觉循环。 与触觉循环同步的线程安全方法。
场景设置
触觉环路
添加新的 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 的软件包管理器中导入。