位置控制简易教程
本教程将向您展示如何在 Unity 场景中通过一个动态 GameObject 来控制Inverse3 设备的光标位置,并在此基础上进一步扩展了“入门指南”中的相关概念。
引言
Inverse3 设备支持两种控制模式: 力控制 und 位置控制.
力控制会根据光标位置调整力,而位置控制则直接控制光标位置。
本教程使用了来自 动态场景中的力反馈教程 并侧重于使用 CursorSetPosition innerhalb der Methode FixedUpdate,以便设备的光标能够跟随移动中的 GameObject。
场景设置
请从 动态场景中的力反馈教程, 其中一个 触觉装置 以及一个 GameObject 移动球 包括由该组件 MovableObject 由……控制。
SpherePositionControl 组件的实现
更换该部件 球体力反馈 am GameObject 移动球 通过一个名为 SpherePositionControl.cs.
在类中定义 SpherePositionControl 具有以下特性:
public Inverse3 inverse3;
public float minSyncDistance = 0.05f;
private bool _isCursorSynchronized;
- inverse3: 指在“检查器”中设置的Inverse3 设备的组件。
- minSyncDistance:开始进行光标同步时的最小距离。
- _isCursorSynchronized:一个标志,用于指示光标的移动是否与“移动球”同步。
同步逻辑
请实现相关方法,根据与移动球的距离来启动和停止光标同步:
private void StartSynchronizeCursor()
{
var cursorPosition = inverse3.Cursor.transform.position;
GetComponent<MovableObject>().SetTargetPosition(cursorPosition, teleport: true);
_isCursorSynchronized = true;
}
private void StopSynchronizeCursor()
{
_isCursorSynchronized = !inverse3.Release();
}
这里是
MovableObject.SetTargetPosition(position, teleport:true)被使用,从而导致 移动球 被传送到光标位置。
Methoden Update 和 FixedUpdate
在该方法中切换 Update 光标同步取决于光标与 移动球 嗯:
private void Update()
{
var distance = Vector3.Distance(inverse3.CursorPosition, transform.position);
if (!_isCursorSynchronized && distance <= minSyncDistance)
{
StartSynchronizeCursor();
}
else if (_isCursorSynchronized && distance > minSyncDistance)
{
StopSynchronizeCursor();
}
}
请在 FixedUpdate 将光标的位置调整为与 移动球 如果同步功能处于启用状态,则对应于:
private void FixedUpdate()
{
if (_isCursorSynchronized)
{
inverse3.SetCursorPosition(transform.position);
}
}
请使用 FixedUpdate 方法,以确保位置控制能够以稳定的帧率运行,而不受图形渲染性能的影响。
初始化
请在 Awake() 确保该 移动球 从Inverse3 设备能够触及的位置开始,无论该设备是左撇子还是右撇子:
private void Awake()
{
inverse3.Ready.AddListener(device =>
{
GetComponent<MovableObject>().SetTargetPosition(((Inverse3)device).WorkspaceCenterLocalPosition, teleport: true);
});
}
游戏体验
请固定好Inverse3 设备,并确保留有足够的空间。 当您启用“播放”模式并将光标移向“移动球”时,Inverse3 设备会跟随“移动球”的移动。 通过键盘输入可以移动“移动球”,从而演示光标追踪其位置的能力。

源文件
本教程的完整场景及相关文件,请参见示例 教程 我是 Unity 的包管理器。
其中包括该脚本 MovableObject,该功能在多个示例中被用于通过键盘输入来控制 GameObject 的移动。
SpherePositionControl.cs
/*
* Copyright 2024 Haply Robotics Inc. All rights reserved.
*/
using Haply.Inverse.DeviceControllers;
using Haply.Samples.Tutorials.Utils;
using UnityEngine;
namespace Haply.Samples.Tutorials._5_SimplePositionControl
{
/// <summary>
/// Controls the Inverse3 cursor position based on the current position of this GameObject.
/// When the GameObject is within a specified distance from the cursor, it initiates synchronized control,
/// allowing the cursor to follow the GameObject's movements.
/// </summary>
[RequireComponent(typeof(MovableObject))]
public class SpherePositionControl : MonoBehaviour
{
public Inverse3Controller inverse3;
[Tooltip("Minimum distance required to initiate synchronized control between this GameObject and the Inverse3 cursor.")]
[Range(0, 1)]
public float minSyncDistance = 0.05f;
private bool _isCursorSynchronized;
private void Awake()
{
// Ensure inverse3 is set, finding it in the scene if necessary.
inverse3 ??= FindFirstObjectByType<Inverse3Controller>();
// When inverse3 is ready, so the handedness is defined
inverse3.Ready.AddListener((device, args) =>
{
// Teleport the sphere to its workspace center to ensure it can be reached,
// regardless of whether the device is left or right-handed. This ensures the GameObject starts in a
// position that is accessible by the Inverse3 device.
GetComponent<MovableObject>().SetTargetPosition(device.WorkspaceCenterLocalPosition, teleport:true);
});
}
private void OnDisable()
{
// Ensure movement synchronization is disabled when the component is disabled.
StopSynchronizeCursor();
inverse3.Release();
}
private void Update()
{
if (!inverse3.IsReady)
{
return;
}
// Calculate the distance between the Inverse3 position and this object's position.
var distance = Vector3.Distance(inverse3.CursorPosition, transform.position);
// Enable synchronized movement if within the minimum sync distance and not already synced.
if (!_isCursorSynchronized && distance <= minSyncDistance)
{
StartSynchronizeCursor();
}
// Disable synchronized movement if outside the minimum sync distance and currently synced.
else if (_isCursorSynchronized && distance > minSyncDistance)
{
StopSynchronizeCursor();
}
}
private void FixedUpdate()
{
if (_isCursorSynchronized)
{
// If in sync, set the Inverse3 cursor position to this object's position.
inverse3.SetCursorPosition(transform.position);
}
else
{
inverse3.ProbeCursorPosition(true);
}
}
private void StartSynchronizeCursor()
{
// Get the current cursor position.
var cursorPosition = inverse3.Cursor.transform.position;
// Teleport this object to the cursor position to avoid a sudden jump when position control starts.
GetComponent<MovableObject>().SetTargetPosition(cursorPosition, teleport:true);
// Start synchronizing the movement of this object with the cursor.
_isCursorSynchronized = true;
}
private void StopSynchronizeCursor()
{
// Stop synchronizing the movement.
_isCursorSynchronized = !inverse3.Release();
}
}
}