Skip to main content

Class UBhapticsSDK2

Inherits from UBlueprintFunctionLibrary


Class UBhapticsSDK2 contains the functions for using haptic devices from bHaptics.

References

ModuleBhapticsPlugin
HeaderEngine\Plugins\Marketplace\BhapticsPlugin\Source\BhapticsPlugin\Public\BhapticsSDK2.h
Include#include "BhapticsSDK2.h"

Static Functions — Play Event-driven Haptic

Play the haptic patterns bound to specific haptic event made from Designer/Portal. We highly recommend to use these functions.

PlayHaptic

static int PlayHaptic(FString eventId);

Play the haptic event. It is the most basic way to call a haptic event. It has the lowest overhead of any haptic event-calling function.

Parameters

  • FString eventId: Name of haptic event which you want to play.

Returns

Request ID. You can use the request ID to stop the haptic. It returns -1 if the return fails.

Example

#include "BhapticsSDK2.cpp"

void AExample::Shoot()
{
// Assuming the event name is "shootpistol"
UBhapticsSDK2::PlayHaptic("shootpistol");
}

PlayHapticWithOption

static int PlayHapticWithOption(FString eventId, float intensity = 1.0f, float duration = 1.0f, float angleX = 0.0f, float offsetY = 0.0f);

Play haptic event, with adjusting the strength, duration, and direction of the haptic.

Parameters

  • FString eventId: Name of haptic event which you want to play.
  • float intensity: The haptic intensity is multiplied by this value.
  • float duration: The haptic duration is multiplied by this value.
  • float angleX: Rotate haptic counterclockwise around the global Vector3.up. Valid range is: [0.0f - 360.0f]
  • float offsetY: Move haptic up or down. Valid range is: [-0.5f - 0.5f]

Returns

Request ID. You can use the request ID to stop the haptic. It returns -1 if the return fails.

Example

#include "BhapticsSDK2.cpp"

void AExample::Shoot()
{
UBhapticsSDK2::PlayHapticWithOption(
"shootpistol", // Haptic name
1.0f, // Haptic intensity
1.0f, // Haptic duration
0.0f, // Rotate haptic around global Vector3.up (0f - 360f)
0.0f // Move haptic up or down (-0.5f - 0.5f)
);
}

PlayLoop

static int PlayLoop(FString eventId, float intensity = 1.0f, float duration = 1.0f, float angleX = 0.0f, float offsetY = 0.0f, int interval = 200, int maxCount = 999999);

Play the haptic repeatedly. Additionally, like the function PlayHapticWithOption, you can adjust the strength, duration, and direction of the haptic.

Parameters

  • FString eventId: Name of haptic event which you want to play.
  • float intensity: The haptic intensity is multiplied by this value.
  • float duration: The haptic duration is multiplied by this value.
  • float angleX: Rotate haptic counterclockwise around the global Vector3.up. Valid range is: [0.0f - 360.0f]
  • float offsetY: Move haptic up or down. Valid range is: [-0.5f - 0.5f]
  • int interval: The time interval between loops, measured in milliseconds.
  • int maxCount: The number of loops.

Returns

Request ID. You can use the request ID to stop the haptic. It returns -1 if the return fails.

Example

#include "BhapticsSDK2.cpp"

void AExample::Shoot()
{
UBhapticsSDK2::PlayLoop(
"shootpistol", // Haptic name
1.0f, // Haptic intensity
1.0f, // Haptic duration
0.0f, // Rotate haptic around global Vector3.up (0f - 360f)
0.0f, // Move haptic up or down (-0.5f - 0.5f)
200, // Loop interval time (millisecond)
999999 // Loop count
);
}

Static Functions — Play Haptic Directly

If you want to play haptics without creating a new event, use these functions.

PlayDot

static int PlayDot(int position, TArray<int> motorValues, float seconds = 0.5f);

Play haptic feedback on the specific haptic actuator. You can use this function without creating an event.

Parameters

  • int position: Type of haptic device.

    ValueDeviceSame as…
    0TactSuitEBhapticsDevicePosition::Vest
    1Tactosy for Arms(Left)EBhapticsDevicePosition::ForearmL
    2Tactosy for Arms(Right)EBhapticsDevicePosition::ForearmR
    3TactVisorEBhapticsDevicePosition::Head
    4Tactosy for Hands(Left)EBhapticsDevicePosition::HandL
    5Tactosy for Hands(Right)EBhapticsDevicePosition::HandR
    6Tactosy for Feet(Left)EBhapticsDevicePosition::FootL
    7Tactosy for Feet(Right)EBhapticsDevicePosition::FootR
    8TactGlove(Left)EBhapticsDevicePosition::GloveL
    9TactGlove(Right)EBhapticsDevicePosition::GloveR
  • TArray<int> motorValues: Assign the length of the array by the number of motors for device. Values in the array means motors' intensity. Valid range for each value in the array is: [1 - 100]

  • float seconds: The duration of haptic, measured in second. Greater than or equal to 0.1f is recommended.

Returns

Request ID. You can use the request ID to stop the haptic. It returns -1 if the return fails.

Example

#include "BhapticsSDK2.cpp"

void AExample::Shoot()
{
// TactSuit has 40 motors, so length of array should be 40 too.
TArray<int> MotorValueArray = TArray<int>{
50, 40, 30, 20, 10, 50, 40, 30, 20, 10,
50, 40, 30, 20, 10, 50, 40, 30, 20, 10,
50, 40, 30, 20, 10, 50, 40, 30, 20, 10,
50, 40, 30, 20, 10, 50, 40, 30, 20, 10};

UBhapticsSDK2::PlayDot(
(int)EBhapticsDevicePosition::Vest, // Device type
MotorValueArray, // Haptic intensities
0.5f // Haptic duration (millisecond)
);
}

PlayPath

static int PlayPath(int position, TArray<float> x, TArray<float> y, TArray<int> motorValues, float seconds = 0.5);

Play haptic around specific coordinates. Unlike PlayDot function, which specifies the haptic intensity for each haptic actuator individually, this method specify the haptic intensity for particular coordinates.

When specifying haptic position, PlayMotors offers discrete control, while PlayPath is more continuous. PlayMotors assigns intensity to individual actuators, whereas PlayPath assigns intensity for specific coordinates (between 0 and 1 for both X and Y axis), causing nearby actuators to vibrate accordingly.

You can put multiple coordinates with multiple intensities in the array. Note that all actuators around these coordinates in the array will activate simultaneously (at the same time), not sequentially. Moreover, the size of all arrays must be the same.

By continuously calling this function while gradually changing the values, you can achieve the effect of a moving haptic point.

Frame 82.png

Parameters

  • int position: Type of haptic device.

    ValueDeviceSame as…
    0TactSuitEBhapticsDevicePosition::Vest
    1Tactosy for Arms(Left)EBhapticsDevicePosition::ForearmL
    2Tactosy for Arms(Right)EBhapticsDevicePosition::ForearmR
    3TactVisorEBhapticsDevicePosition::Head
    4Tactosy for Hands(Left)EBhapticsDevicePosition::HandL
    5Tactosy for Hands(Right)EBhapticsDevicePosition::HandR
    6Tactosy for Feet(Left)EBhapticsDevicePosition::FootL
    7Tactosy for Feet(Right)EBhapticsDevicePosition::FootR
    8TactGlove(Left)EBhapticsDevicePosition::GloveL
    9TactGlove(Right)EBhapticsDevicePosition::GloveR
  • TArray<float> x: Assign X coordinate. Valid range for each value in the array is: [0.0f - 1.0f]

  • TArray<float> y: Assign Y coordinate. Valid range for each value in the array is: [0.0f - 1.0f]

  • TArray<int> motorValues: Assign the length of the array by the number of coordinate. Values in the array means coordinates' intensity. Valid range for each value in the array is: [1 - 100]

  • float seconds: The duration of haptic, measured in second. Greater than or equal to 0.1f is recommended.

Returns

Request ID. You can use the request ID to stop the haptic. It returns -1 if the return fails.

Example

#include "BhapticsSDK2.cpp"

/* Assumption:
- For TactSuit
- Coordinate with Intensity
- (X: 0.1, Y: 0.2) Intensity 40
- (X: 0.3, Y: 0.4) Intensity 80
- (X: 0.5, Y: 0.6) Intensity 10
- Duration 0.5 second
*/
void AExample::Shoot()
{
UBhapticsSDK2::PlayPath(
(int)EBhapticsDevicePosition::Vest, // Device Type
TArray<float>{0.1f, 0.3f, 0.5f}, // X Coordinates
TArray<float>{0.2f, 0.4f, 0.6f}, // Y Coordinates
TArray<int>{40, 80, 10}, // Intensities
0.5f // Duration
);
}

PlayWaveform

static int PlayWaveform(int position, TArray<int> motorIntensities, TArray<EBhapticsGlovePlayTime> playTimeValues, TArray<EBhapticsGloveShapeValue> shapeValues);

TactGlove Only. Play haptics in TactGlove. Unlike using PlayDot, you can finely adjust haptic duration and vibration intensity changes. This allows for even finer expression of haptic feedback.

Each array must have six elements, and at least one element is required to work.

Parameters

  • int position: Type of haptic device.

    ValueDeviceSame as…
    8TactGlove(Left)EBhapticsDevicePosition::GloveL
    9TactGlove(Right)EBhapticsDevicePosition::GloveR
  • TArray<int> motorIntensities: An array consisting of six elements, each representing the intensity of a motor. The array must have a length of six, as there are six motors in one TactGlove. Valid range for each value in the array is: [1 - 100]

    Array IndexMotor is positioned at…
    0Tip of the thumb
    1Tip of the index finger
    2Tip of the middle finger
    3Tip of the ring finger
    4Tip of the little finger
    5On the wrist
  • TArray<EBhapticsGlovePlayTime> playTimeValues: An array consisting of six elements, each representing a time interval for actuation, with time defined using EBhapticsGlovePlayTime enums.

    ValueDurationSame as…
    EBhapticsGlovePlayTime::NoneNone0
    EBhapticsGlovePlayTime::FiveMS5ms1
    EBhapticsGlovePlayTime::TenMS10ms2
    EBhapticsGlovePlayTime::TwentyMS20ms4
    EBhapticsGlovePlayTime::ThirtyMS30ms6
    EBhapticsGlovePlayTime::FortyMS40ms8
  • TArray<EBhapticsGloveShapeValue> shapeValues: An array consisting of six elements, each representing the forms of haptic intensity changes over time, specified by the EBhapticsGloveShapeValue enums.

    ValueWaveformSame as…
    EBhapticsGloveShapeValue::ConstantConstant intensity for the duration0
    EBhapticsGloveShapeValue::DecreasingStarts at the specified intensity and decreases by half1
    EBhapticsGloveShapeValue::IncreasingStarts at half of the specified intensity and increases to the specified one.2

Returns

Request ID. You can use the request ID to stop the haptic. It returns -1 if the return fails.

Example

#include "BhapticsSDK2.cpp"

void AExample::Shoot()
{
TArray<int> GloveMotorValue = TArray<int>{50, 50, 50, 50, 50, 50};

TArray<EBhapticsGlovePlayTime> GlovePlayTime = {
EBhapticsGlovePlayTime::FiveMS, EBhapticsGlovePlayTime::TenMS,
EBhapticsGlovePlayTime::TwentyMS, EBhapticsGlovePlayTime::ThirtyMS,
EBhapticsGlovePlayTime::FortyMS, EBhapticsGlovePlayTime::None};

TArray<EBhapticsGloveShapeValue> GloveShapeValue = {
EBhapticsGloveShapeValue::Constant, EBhapticsGloveShapeValue::Decreasing,
EBhapticsGloveShapeValue::Increasing, EBhapticsGloveShapeValue::Constant,
EBhapticsGloveShapeValue::Decreasing, EBhapticsGloveShapeValue::Increasing};

UBhapticsSDK2::PlayWaveform(
(int)EBhapticsDevicePosition::GloveL, // Device Type
GloveMotorValue, // Intensities
GlovePlayTime, // Intervals
GloveShapeValue // Intensity changing forms
);
}

Static Functions — Others

StopHapticByEventId

static bool StopHapticByEventId(FString eventId);

Stop the haptic event by Event ID. Returns whether the stop was successful.

#include "BhapticsSDK2.cpp"

void AExample::Example()
{
UBhapticsSDK2::StopHapticByEventId("eventID");
}

StopHapticByRequestId

static bool StopHapticByRequestId(int requestId);

Stop the Haptic Event by using the Request ID from the return of the function that executes the haptic. Returns whether the stop was successful.

#include "BhapticsSDK2.cpp"

void AExample::Example()
{
int RequestID = UBhapticsSDK2::PlayHaptic("eventID");
UBhapticsSDK2::StopHapticByRequestId(RequestID);
}

StopHaptic

static bool StopHaptic();

Stops all haptic currently playing. Returns whether the stop was successful.

#include "BhapticsSDK2.cpp"

void AExample::Example()
{
UBhapticsSDK2::PlayHaptic("bangbang");
UBhapticsSDK2::PlayHaptic("eventID");
UBhapticsSDK2::PlayHaptic("explosion");

UBhapticsSDK2::StopHaptic();
}

IsPlaying

static bool IsPlaying();

Check if the haptic is playing.

#include "BhapticsSDK2.cpp"

void AExample::Example()
{
if (UBhapticsSDK2::IsPlaying())
{
StopHaptic();
}
}

IsPlayingByEventId

static bool IsPlayingByEventId(FString eventId);

Check if the haptic event for this Event ID is playing.

#include "BhapticsSDK2.cpp"

void AExample::Example()
{
UBhapticsSDK2::PlayHaptic("eventID");

if (UBhapticsSDK2::IsPlayingByEventId("eventID"))
{
UBhapticsSDK2::StopHapticByEventId("eventID");
}
}

IsPlayingByRequestId

static bool IsPlayingByRequestId(int requestId);

Check if the haptic event for this Request ID is playing.

#include "BhapticsSDK2.cpp"

void AExample::Example()
{
int RequestID = UBhapticsSDK2::PlayHaptic("eventID");
if (UBhapticsSDK2::IsPlayingByRequestId(RequestID))
{
UBhapticsSDK2::StopHapticByRequestId(RequestID);
}
}

Initialize

static void Initialize();

Initialize the haptic environment. This function should be called before using the haptic-related functions.

Ping

static void Ping(FBhapticsDevice device);

Send simple haptic feedback to certain device.

PingAll

static void PingAll();

Send simple haptic feedback to all connected devices.

Destroy

static void Destroy();

Destroy the haptic environment. This function must be called when game ends, and called ONLY ONCE.

GetBhapticsDevices

static TArray<FBhapticsDevice> GetBhapticsDevices();

Get an array of connected haptic devices' info.

IsBhapticsAvailable

static bool IsBhapticsAvailable();

Check if the haptic environment is initialized, and ready to use haptic-related functions.

ProjectToVest

static FBhapticsRotationOption ProjectToVest(
FVector ContactLocation,
UPrimitiveComponent* PlayerComponent,
float HalfHeight = 0
);

Helper function to compute the offset values (angle and height) of a given collision contact point from the player. These offset values can be used in PlayHapticWithOption and PlayLoop which can adjust the haptic position.

This function assumes that the forward direction aligns with the front of the vest, and the player's position is considered as the origin.

Check out the example below for detailed information.

Parameters

  • FVector ContactLocation: Contact point in global coordinates.
  • UPrimitiveComponent* PlayerComponent: Reference to the primitive component attached to the player.
  • float HalfHeight: The half value of the player's actual height, measured in centimeter.

Example

Let's assume implementing haptic when getting shot in a VR game. The corresponding haptic pattern for this event would be a short and strong haptic feedback at the center front of the TactSuit. To enhance realism, varying the height and angle of the haptic feedback based on where the player is shot would be ideal.

The PlayHapticWithOption and PlayLoop functions allow for adjusting the height and angle of the haptic pattern. These functions take angle(OffsetAngleX) and height(OffsetY) values for haptic adjustment.

The ProjectToVest function calculates the angle and height values based on where the player is shot, the player's transform information, and the user's height. These values are then encapsulated in the FBhapticsRotationOption structure and returned.

Frame 81 (1).png

#include "BhapticsSDK2.cpp"

void AExample::HitByBullet()
{
APawn *PlayerPawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
UPrimitiveComponent *PlayerComponent = Cast<UPrimitiveComponent>(PlayerPawn->GetRootComponent());

FVector ContactLocation = USomewhere::GetContactLocationSomehow();
float HalfHeight = YourActualHeight / 2;

FBhapticsRotationOption result = UBhapticsSDK2::ProjectToVest(ContactLocation, PlayerComponent, HalfHeight);

UBhapticsSDK2::PlayHapticWithOption("hit_by_bullet", 1.0f, 1.0f, result.OffsetAngleX, result.OffsetY);
}

ProjectToVestLocation

static FBhapticsRotationOption ProjectToVestLocation(FVector ContactLocation, FVector PlayerLocation, FRotator PlayerRotation);

Helper function to compute offset values from a contact location and player transform information. It's similar to ProjectToVest, but it only calculates the angle offset(OffsetAngleX). The height(OffsetY) will always be 0.

Parameters

  • FVector ContactLocation: Contact point in global coordinates.
  • FVector PlayerLocation: Location of the player.
  • FRotator PlayerRotation: Rotation of the player.

CustomProjectToVest

static FBhapticsRotationOption CustomProjectToVest(FVector ContactLocation, UPrimitiveComponent* PlayerComponent, float HalfHeight = 0, FVector UpVector = FVector::ZeroVector, FVector ForwardVector = FVector::ZeroVector);

Helper function to compute offset values from collision. Performs the same function as ProjectToVest, but allows the Forward and Up vectors to be changed.

  • FVector ContactLocation: Contact point in global coordinates.
  • UPrimitiveComponent* PlayerComponent: Reference to the primitive component attached to the player.
  • float HalfHeight: The half value of the player's actual height, measured in centimeter.
  • FVector UpVector: The reference upward direction vector for offset calculation.
  • FVector ForwardVector: The reference forward direction vector for offset calculation.