Accessing HTC Vive controllers from C++ in UE4 (4.13 and 4.14)

If you start playing with your HTC Vive HMD together with Unreal Engine 4 you’ll probably start with this tutorial: https://docs.unrealengine.com/latest/INT/Platforms/SteamVR

It shows how to set up the HMD and creates a Blueprint Pawn that uses it. Once you have this running you can easily build an example level using the controllers as described here: https://docs.unrealengine.com/latest/INT/Platforms/VR/MotionController

However, if you’re a C++ programmer like me and don’t quite get the point of drawing logics with Blueprint, you might find the following useful. I’ll show you how to access all buttons available on the current HTC Vive controllers.

Binding the input events in the editor

As you already might know there are two different kinds of input events one can bind to in UE4: Action and Axis. In Project Settings->Engine->Input you can map those inputs to friendly names that you can later use in your C++ code:

Action Mapping
Map to discrete events like hitting a button
Axis Mapping
These inputs are continuously polled (every frame) and may have a continuous range (typically 0-1)

So what are the input events of an HTC Vive controller that you can map? Let’s start with the discrete events:

  • Shoulder (menu button pressed)
  • Thumbstick (touchpad pressed)
  • FaceButton1-4 (touchpad pressed directional: up, right, bottom, left)
  • Steam Touch 1 (touchpad touched)
  • Grip1 (one of the buttons on the side is pressed)
  • Trigger (Trigger fully pulled)

All these Mappings can be set in Project Settings->Engine->Input->BindingsCreate a new Action (or Axis) mapping, give it a name like LeftMenuButton (or LeftTriggerAnalog) and then search for the corresponding input name. It would be MotionController (L) Shoulder for the left Menu button press event:

capture

 

 

 

 

 

 

 

Most mappings have the same name structure like in the screen shot: MotionController (L/R) <name> with <name> being

  • Shoulder
  • Thumbstick
  • FaceButton1-4
  • Grip1
  • Trigger

Mapping the touchpad touched event works slightly different. The mappings are called Steam Touch 0 for the left controller and Steam Touch 1 for the right controller.

Now that you know how to set the Input mappings for discrete actions, let’s go to the axes. The variable values that you might want to poll are:

  • TriggerAxis (how far is the trigger pulled: values may go from 0 to about 0.9; 0.9-1.0 triggers the action)
  • Thumbstick X-Axis (position of the thumb, from left to right means -1 < X < 1)
  • Thumbstick Y-Axis (position of the thumb, from top to bottom means -1 < Y < 1)

The mapping names are again like following: MotionController (L/R) <name>

capture

 

 

 

 

So you can map up to 12 input events for each controller. That’s how a Project/Config/DefaultInput.ini might look like after setting all mappings for both controllers (24 total):

 Using the mappings in C++

So now that we’ve mapped the input actions and axes to nice names, we can use those to bind functions to those. This means every time the event is triggered (actions) or the value is polled (axes), the given function is called by the engine.

Actions

In our case all action mappings are like buttons: they can be pressed and released. That’s why we’ll have two functions for every action mapped. Let’s do that for the LeftTouchpadPress mapping in the SetupPlayerInputComponent method of our character class:

So now MotionControlLeftTouchpadPressed will be called whenever you start touching the touchpad of the left controller and MotionControlLeftTouchpadReleased will be called as soon as you remove your thumb from the touchpad. The same can be done for all other mapped actions (see further below).

Axes

With the axes being mapped to a nice name we can bind to those in C++. This means that they will be polled regularly by the engine and the resulting value will be pushed to a function that we have to provide:

In this case the delegate function MotionControlLeftTriggerAnalog receives a parameter of type float which will be the value of the axis:

Now MotionControlLeftTriggerAnalog will get called every frame with the current value of the left controller trigger, even if it’s 0.0 (not touched at all).

 All the code

Now that we have all the mappings and know how to bind to them in C++, we can create a simple character class that prints whenever you push or touch an input element of your HTC Vive controller: