주요 콘텐츠로 건너뛰기
버전: 2.0.0

버즈그립 위치 제어 튜토리얼

이 튜토리얼에서는 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.LocalRotation * Vector3.forward;

// Check if the VerseGrip button is pressed down
if (grip.GetButtonDown())
{
// Initialize target position
_targetPosition = inverse3.LocalPosition;
}

// 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.TryResetForce();
}
}

게임 플레이

  • 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.TryResetForce();
}
}

private void OnDeviceStateChanged(VerseGrip grip)
{
// Calculate the direction based on the VerseGrip's rotation
var direction = grip.LocalRotation * Vector3.forward;

// Check if the VerseGrip button is pressed down
if (grip.GetButtonDown())
{
// Initialize target position
_targetPosition = inverse3.LocalPosition;
}

// 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);
}
}
}