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

기본 힘과 위치 튜토리얼

이 가이드는 힘을 가하고 Inverse3 커서의 움직임을 시각화하는 간단한 데모를 제공합니다. 마지막으로 Inverse3 은 가상의 고무 밴드로 시작 위치에 묶여 있는 느낌을 시뮬레이션하고 구형 게임 오브젝트가 커서의 위치를 표시합니다.

소개

빠른 시작 가이드에서는 Inverse3 객체와 그 기능, 그리고 일정한 힘을 생성하는 방법을 소개했습니다. 여기서 우리의 목표는 커서에 고무줄 효과를 시뮬레이션하는 것입니다. 고무줄은 스프링과 유사하게 작동하므로 힘은 강성과 두 끝점 사이의 거리 모두에 영향을 받습니다. 따라서 위치와 강성이 주어지면 커서가 원점에서 멀어지지 않도록 저항하는 힘을 생성하는 함수를 고안하는 것이 목표입니다.

장면 설정

게임 오브젝트 > Haply 메뉴에서 햅틱 릭(한 손) 을 생성하여 시작합니다.

ForceAndPosition 컴포넌트

를 선택하고 햅틱 오리진 게임 오브젝트에서 새 스크립트를 추가합니다. ForceAndPosition.cs 를 클릭하고 ForceAndPosition 클래스에 다음 코드를 추가합니다:

[SerializeField]
private Inverse3 inverse3 = null;

[SerializeField, Range(0, 400)]
private float stiffness = 100;

private Vector3 _initialPosition = Vector3.zero;

private Vector3 ForceCalculation(in Vector3 position)
{
if (_initialPosition == Vector3.zero)
{
// Save the initial device effector position
_initialPosition = position;
}
// Return force opposing movement from the initial position
return (_initialPosition - position) * stiffness;
}

이 세그먼트는 강성을 100N/m(뉴턴/미터)로 설정하여 비교적 부드러운 스프링을 시뮬레이션합니다. 또한 다음을 소개합니다. _initialPosition커서의 시작 위치를 캡처하는 벡터입니다. 벡터의 ForceCalculation 메서드는 처음 실행되는 동안 초기 위치를 기록하고 이후 커서의 움직임에 반대되는 힘 출력을 계산합니다.

통합 OnDeviceStateChanged 콜백의 OnEnable 그리고 OnDisable 메서드에 설명된 대로 빠른 시작 가이드:

protected void OnEnable()
{
inverse3.DeviceStateChanged += OnDeviceStateChanged;
}

protected void OnDisable()
{
inverse3.DeviceStateChanged -= OnDeviceStateChanged;
}

게임 플레이

Inverse3 커서를 잡고 재생 모드를 활성화한 다음 기기를 조작해 봅니다. 커서를 움직이면 힘이 발생하는 것을 확인할 수 있습니다. 커서가 시작 위치에서 더 멀리 이동할수록 이 힘은 더 뚜렷해집니다.

커서 이동

소스 파일

이 예제에서 사용된 최종 씬과 모든 관련 파일은 Unity 패키지 관리자의 튜토리얼 샘플에서 임포트할 수 있습니다.

ForceAndPosition.cs

/*
* Copyright 2024 Haply Robotics Inc. All rights reserved.
*/

using Haply.Inverse.Unity;
using UnityEngine;

namespace Haply.Samples.Tutorials._1_ForceAndPosition
{
/// <summary>
/// Demonstrates the application of force to maintain the cursor at its initial position.
/// </summary>
public class ForceAndPosition : MonoBehaviour
{
// Must be assigned in inspector
public Inverse3 inverse3;

[Range(0, 400)]
// Stiffness of the force feedback.
public float stiffness = 100;

// Stores the initial position of the cursor.
private Vector3 _initialPosition = Vector3.zero;

/// <summary>
/// Subscribes to the DeviceStateChanged event when the component is enabled.
/// </summary>
protected void OnEnable()
{
inverse3.DeviceStateChanged += OnDeviceStateChanged;
}

/// <summary>
/// Unsubscribes from the DeviceStateChanged event and reset the force when the component is disabled.
/// </summary>
protected void OnDisable()
{
inverse3.DeviceStateChanged -= OnDeviceStateChanged;
}

/// <summary>
/// Calculates the force required to maintain the cursor at its initial position.
/// </summary>
/// <param name="position">The current position of the cursor.</param>
/// <returns>The calculated force vector.</returns>
private Vector3 ForceCalculation(in Vector3 position)
{
if (_initialPosition == Vector3.zero)
{
// save the first device effector position
_initialPosition = position;
}
// return opposite force to stay at initial position
return (_initialPosition - position) * stiffness;
}

/// <summary>
/// Event handler that calculates and send the force to the device when the cursor's position changes.
/// </summary>
/// <param name="device">The Inverse3 device instance.</param>
private void OnDeviceStateChanged(Inverse3 device)
{
// Calculate the force.
var force = ForceCalculation(device.CursorLocalPosition);

// Apply the force to the cursor.
inverse3.CursorSetLocalForce(force);
}
}
} // namespace Haply.Samples.Tutorials._1_ForceAndPosition