Advanced VR Interactions in Unity Tutorial

Create advanced interactions and mechanics in your Unity VR app, including working with tooltips, joints, snapping and haptic feedback! By Eric Van de Kerckhove.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 4 of 4 of this article. Click here to view the first page.

Haptic Feedback

There are a few ways to add haptic feedback (or vibration) to interactions, such as adding a component that handles the haptics.

Add a new empty GameObject to the Hierarchy, name it BombToy, and parent it to RW Props. Set its Position to (X:8, Y:1.11, Z:6.5), and drag the Bomb model from the Razeware\Models folder onto the newly made GameObject to give it some visuals.

Reset the Bomb Position to (X:0, Y:0, Z:0); and to size it down a bit, set its scale to (X:18.5, Y:18.5, Z:18.5). You’ll now have a bomb sitting on the table:

Don’t worry; it’s safe!

Select BombToy and open the VRTK setup wizard (via Window ▸ VRTK); leave everything at their default values and click the Setup selected object(s) button.

Add a Sphere Collider component to the BombToy with a Radius of 0.105 to prevent it from dropping through the floor.

The component you’re interested in is VRTK_Interact Haptics. Until now, you’ve removed this as it wasn’t needed for the other objects.

To get it to work, you’ll need to tweak its variables.

Set Strength On Touch to 0.2, Duration On Touch to 0.1 and Interval On Touch to 0.1 as well in the Haptics On Touch section.

This gives a light and short vibration when you touch the bomb with your controller.

To make it vibrate when you grab it, change the following:

Set Strength On Grab to 0.4, Duration On Grab to 0.2 and Interval On Grab to 0.05 as well in the Haptics On Grab section. This causes the controller to vibrate a bit more violently, letting you know you’ve successfully grabbed the object.

Drag the BombToy to the Razeware\Prefabs\Grab folder to turn it into a prefab. Test if the bomb works as intended by running the scene then touching and grabbing the bomb.

You can also create more interesting effects by creating your own scripts to handle the haptics. To demonstrate, you’ll add a pulse-effect to the battery while you hold it.

Create a new C# script in the Razeware\Scripts folder, name it PulseOnHold, and open it in your code editor.

Remove the Start() and Update() methods, and add the following line below the other using statements:

using VRTK;

Now replace this line:

public class PulseOnHold : MonoBehaviour {

With this one:

public class PulseOnHold : VRTK_InteractableObject {

This causes the script to derive from InteractableObject, which includes some essential functionality.

Now, add the following variables below the class declaration:

public float pulseInterval = 2f; // 1
public float pulseDuration = .2f; // 2

private VRTK_ControllerReference controllerReference; // 3
private IEnumerator pulseRoutine; // 4

Here’s what they’re used for:

  1. The time between every pulse.
  2. The amount of time the pulse lasts.
  3. A reference to the controller that receives the vibration.
  4. A cached coroutine for correctly starting and stopping the haptic feedback.

Add the following coroutine to do the vibrating:

IEnumerator DoPulsing()
{
    while (gameObject.activeSelf)
    {
        VRTK_ControllerHaptics.TriggerHapticPulse(controllerReference, 0.5f, pulseDuration, 0.01f);
        yield return new WaitForSeconds(pulseInterval);
    }
}

This keeps vibrating the controller at the specified interval until the GameObject gets deactivated or the coroutine is stopped.

Next, add the following methods:

private void OnEnable() // 1
{
    base.OnEnable();
    pulseRoutine = DoPulsing();
}

public override void Grabbed(VRTK_InteractGrab grabbingObject) // 2
{
    base.Grabbed(grabbingObject);
    controllerReference =
        VRTK_ControllerReference.GetControllerReference(grabbingObject.controllerEvents.gameObject);
    StartCoroutine(pulseRoutine);
}

public override void Ungrabbed(VRTK_InteractGrab grabbingObject) // 3
{
    base.Ungrabbed(grabbingObject);
    controllerReference = null;
    StopCoroutine(pulseRoutine);
}

Here’s the breakdown:

  1. Call the base class OnEnable() method and cache a reference to the DoPulsing() coroutine.
  2. This method gets called when a controller grabs the GameObject to which this script is attached. The grabbingObject is stored as the controller, and the pulse routine is started.
  3. This method gets called when a controller releases the GameObject to which this script is attached. The controller is cleared, and the pulse routine is stopped.

Save the script and return to the Unity editor.

Add the Pulse On Hold component to the Battery, and remove the VRTK_Interactable Object component. Your custom component replaces its functionality.

Next, you’ll take a look at the Pulse On Hold component.

Change the Touch Highlight Color to Pure Yellow (R:255, G:255, B:0) and check Is Grabbable.

Don’t forget to update the base battery prefab by clicking Apply on the Battery GameObject in the Hierarchy.

That’s it! Run the scene and grab the battery. You should feel a pulse as long as you’ve got the battery in your hand. Can you feel the force flow with all that energy?

Where to Go From Here?

You can download the final project from this tutorial using the “Download Materials” button at the top or bottom of this page.

Well done! You now know how to add exciting mechanics to your own VR games.

If you had trouble following along, or you want to compare your project to the sample one, you can find the final project included with this tutorial’s resources files.

Here’s a quick recap of what you did. In this tutorial, you learned how to:

  • Create tooltips for objects and controllers.
  • Fix objects to your controllers.
  • Use joints to accurately pick up objects.
  • Snap objects into place.
  • Use haptic feedback.

If you have any questions or comments, please leave them below!