버즈그립 위치 제어 튜토리얼
이 튜토리얼에서는 VerseGrip의 회전을 사용하여 Inverse3 디바이스의 커서 위치를 직접 제어하고, 고빈도 업데이트를 위해 Unity 메인 스레드를 우회하는 방법을 보여드립니다.
소개
에 표시된 방법과 달리 빠른 시작 가이드표준 업데이트 주파수(60Hz)에서 작동하는 이 튜토리얼은 더 높은 주파수(1~4kHz)에서 VerseGrip 디바이스의 회전에 따라 Inverse3 커서의 위치를 동적으로 조정하는 것을 목표로 합니다.
이를 위해 DeviceStateChanged
이벤트가 촉각 스레드에 의해 트리거됩니다.
장면 설정
햅틱 릭을 생성하여 시작합니다: 빠른 시작 가이드에 설명된 대로 게임 오브젝트 > 햅리 > 햅틱 릭(한 손)을 선택합니다.
VerseGripPositionControl 컴포넌트
라는 이름의 새 C# 스크립트를 만듭니다. VerseGripPositionControl.cs
를 클릭하고 햅틱 오리진 게임 오브젝트.
다음 프로퍼티를 VerseGripPositionControl
클래스:
public Inverse3 inverse3;
public VerseGrip verseGrip;
[Range(0, 1)]
public float speed = 0.5f;
[Range(0, 0.2f)]
public float movementLimitRadius = 0.2f;
private Vector3 _targetPosition;
- inverse3: 인스펙터를 통해 설정한 Inverse3 장치에 대한 참조입니다.
- verseGrip: 커서 제어에 사용되는 VerseGrip 장치에 대한 참조입니다.
- 속도: 커서가 움직이는 속도입니다.
- 움직임 제한 반경: 커서가 초기 위치에서 이동할 수 있는 최대 거리입니다.
- _targetPosition: 커서가 이동하는 목표 위치입니다.
구현 OnDeviceStateChanged
메서드를 사용하여 버즈그립의 회전 및 버튼 입력을 기반으로 커서의 목표 위치를 계산합니다:
private void OnDeviceStateChanged(VerseGrip grip)
{
// Calculate the direction based on the VerseGrip's rotation
var direction = grip.Orientation * Vector3.forward;
// Check if the VerseGrip button is pressed down
if (grip.GetButtonDown())
{
// Initialize target position
_targetPosition = inverse3.CursorLocalPosition;
}
// Check if the VerseGrip button is being held down
if (grip.GetButton())
{
// Move the target position toward the grip direction
_targetPosition += direction * (0.0025f * speed);
// Clamp the target position within the movement limit radius
var workspaceCenter = inverse3.WorkspaceCenter;
_targetPosition = Vector3.ClampMagnitude(_targetPosition - workspaceCenter, movementLimitRadius)
+ workspaceCenter;
// Move cursor to new position
inverse3.CursorSetLocalPosition(_targetPosition);
}
}
등록 및 등록 취소 DeviceStateChanged
이벤트의 OnEnable
그리고 OnDisable
.
/// Subscribes to the DeviceStateChanged event.
private void OnEnable()
{
verseGrip.DeviceStateChanged += OnDeviceStateChanged;
}
/// Unsubscribes from the DeviceStateChanged event.
private void OnDisable()
{
verseGrip.DeviceStateChanged -= OnDeviceStateChanged;
}
선택 사항입니다: 에서 Update
메서드를 사용하여 사용자가 Inverse3의 힘을 재설정할 수 있도록 해 보겠습니다.
private void Update()
{
// Check for space key to disable position control
if (Input.GetKeyDown(KeyCode.Space))
{
// Reset cursor force to disable position control
inverse3.Release();
}
}
게임 플레이
- Inverse3 장치를 고정하고 이동 공간이 충분한지 확인합니다.
- 재생 모드로 들어가서 Inverse3 커서를 길게 누릅니다.
- 버즈그립을 회전하여 Unity 씬에서 커서의 움직임을 관찰하면 버즈그립의 방향과 직접적으로 일치하는 커서의 움직임을 확인할 수 있습니다.
- 버즈그립의 버튼을 누르면 Inverse3 커서가 버즈그립의 회전 방향으로 이동하여 실시간 제어를 보여줍니다.
이 이미지는 커서 모델을 명확하게 하기 위해 앞으로 축을 강조 표시한 것입니다. 커서 모델 사용자 지정에 대한 자세한 내용은 커서 문서를 참조하세요.
소스 파일
이 예제에서 사용된 최종 씬과 모든 관련 파일은 Unity 패키지 관리자의 튜토리얼 샘플에서 임포트할 수 있습니다.
VerseGripPositionControl.cs
/*
* Copyright 2024 Haply Robotics Inc. All rights reserved.
*/
using Haply.Inverse.Unity;
using UnityEngine;
namespace Haply.Samples.Tutorials._6_VerseGripPositionControl
{
/// <summary>
/// Demonstrates how to control the device cursor position using the VerseGrip.
/// </summary>
public class VerseGripPositionControl : MonoBehaviour
{
// Must be assigned in inspector
public Inverse3 inverse3;
public VerseGrip verseGrip;
[Tooltip("Cursor moving speed")]
[Range(0, 1)]
public float speed = 0.5f;
[Tooltip("Maximum radius for cursor movement")]
[Range(0, 0.2f)]
public float movementLimitRadius = 0.2f;
private Vector3 _targetPosition; // Target position for the cursor
/// <summary>
/// Subscribes to the DeviceStateChanged event.
/// </summary>
private void OnEnable()
{
verseGrip.DeviceStateChanged += OnDeviceStateChanged;
}
/// <summary>
/// Unsubscribes from the DeviceStateChanged event.
/// </summary>
private void OnDisable()
{
verseGrip.DeviceStateChanged -= OnDeviceStateChanged;
}
private void Update()
{
// Check for space key to disable position control
if (Input.GetKeyDown(KeyCode.Space))
{
// Reset cursor force to disable position control
inverse3.Release();
}
}
private void OnDeviceStateChanged(VerseGrip grip)
{
// Calculate the direction based on the VerseGrip's rotation
var direction = grip.Orientation * Vector3.forward;
// Check if the VerseGrip button is pressed down
if (grip.GetButtonDown())
{
// Initialize target position
_targetPosition = inverse3.CursorLocalPosition;
}
// Check if the VerseGrip button is being held down
if (grip.GetButton())
{
// Move the target position toward the grip direction
_targetPosition += direction * (0.0025f * speed);
// Clamp the target position within the movement limit radius
var workspaceCenter = inverse3.WorkspaceCenter;
_targetPosition = Vector3.ClampMagnitude(_targetPosition - workspaceCenter, movementLimitRadius)
+ workspaceCenter;
// Move cursor to new position
inverse3.CursorSetLocalPosition(_targetPosition);
}
}
}