141 ratings
Rebinding "Legacy" games for new controllers
By Programmer Joe and 1 collaborators
This is a step-by-step guide on how to rebind a "legacy" game to a new controller using the SteamVR Input system. It will go through three games as examples of this process.
Getting Started with Rebinding
This guide walks you though the process of rebinding an existing "legacy" VR game so it can be played with a new controller. "Legacy" is the word we use for games which don't yet use the SteamVR Input system. As of this writing, that is most VR games and applications on Steam.

The guide will examine three games as case studies, and apply the following steps to each one:
  1. Figure out what actions the user can perform in the game and give them names
  2. Bind those actions to the controller
  3. Test your bindings
  4. Share the binding file so other SteamVR users can take advantage of it

The first step can be tricky, so we'll need to know a few things about the game's input scheme to get it right:
  • Does the game use the two hands interchangeably to perform exactly the same actions? For games that use the hands interchangeably we can do the work once and have it apply to both hands automatically.
  • What simple actions does the game use? Simple actions are ones where the mapping from the controller to the game doesn't involve any complex processing. A good example would be pressing the menu button to open a menu.
  • What are the remaining actions used by the app, and how can we set up "simulated" actions for them? As of this writing, two types of simulated actions are supported: trigger pulls and trackpad clicks. We'll get into both of those in the examples below.

This guide will apply these three steps to a few games with varying binding complexity. We'll be using Knuckles as our example controller, but the same steps apply to custom bindings for Windows MR controllers, Oculus Touch controllers, or really anything else.
Case Study #1 - Jeeboman
Our first case study of how to rebind a game is Jeeboman. This is a straightforward wave shooter that was a launch title for the Vive. The controls are easy to understand, so it is a good place to start.

If you don't happen to own Jeeboman and want to follow along, you can perform these same steps using the Jeeboman Demo.

Defining "actions" for the game

Our first step is to figure out what actions the game has so we know what's bindable. The best way to figure out these actions is to run the game using a controller that the developers of the game have tested with. In Jeeboman's case it's a Vive Controller, and there are four actions: Fire, Select Weapon, Shield, and Pause/Menu.

Now we can set these actions in the binding UI. You can open the UI under the "Devices" menu in the SteamVR status window or use it in-headset. Once you have it open, select Jeeboman from the list of games (you will need to have run it recently). Then select "Edit" under whatever binding you have for the controller type you're binding. In my case it is called "Knuckles Legacy Defaults".

Then select the "Set Up Legacy Actions" tab:

Here you'll see a list of all the bits of data (inputs) a game can query using the old input API. SteamVR doesn't know what the game is doing with any of these bits, just that it might be using them for something. Rebinding a legacy game is a matter of figuring out what bits the game uses, then labeling and organizing them so the rest of the UI is usable by humans.

Because of how little SteamVR knows about the game this screen shows a ton of options by default. What we are doing in this step is providing names for what the game cares about, and hiding everything else. To do that we'll ask ourselves three questions.

Does the game use the controllers interchangeably?

Yes. Each hand has the same four actions. Any weapon can be used to either hand, and buttons affect the hand they are pressed on.

That means we want to check the box at the top labeled "This game expects the left and right hands to use the same actions". Note that when you do this the other tab is renamed to "Legacy Bindings (Mirrored)" to reflect the fact that the right hand is a mirror of the left hand.

What simple "actions" does the game have?

The game exposes four actions:
  • Fire - Trigger Click
  • Select Weapon - Trackpad Click
  • Shield - Grip Button Click
  • Pause/Menu - Application Menu Click

Now that we know what actions Jeeboman has, we can provide names for the things we care about, and get rid of the rest. Let's start with Pause/Menu. The Pause/Menu action happens when the game gets an Application Menu Button click event. So next that input we'll name it Pause/Menu. Jeeboman doesn't use Application Menu Button Touch events (since those didn't exist on the Vive Controller it was developed on) so we'll hide that action.

Now do the same thing for the other three actions and hide the rest. You'll end up with something like this:

If you happen to hide an action that you didn't mean to, you can always press "Show Hidden Actions", find the action in the list, and press "Show" to bring it back.

What complex or "Simulated" actions does the game have?

None. We picked Jeeboman to go first because it is a simple example. We'll get into this question more in the other two examples.

Binding actions to the new controller

Now that we have our actions named, the next step is to bind them to inputs on the controllers. Exactly how to do this depends on the game, but also on your personal preferences. If you don't like the way something is bound, you can always go back and rebind it. Also, if you start with a binding where someone has already done step 1, you can just use their names and skip straight to step 2.

The first action we want to bind is Fire. The trigger is an obvious choice for this action. Usually trigger bindings are mapped like buttons so SteamVR Input will apply a threshold and activate the action when the trigger is partially pulled. To do that we add a "Button" mode to the trigger. Click the "+" next to Trigger and select "Button".

After adding the mode, we want to change the action that is bound to "Click":

The next action to bind is Select Weapon, which was on the Vive controller trackpad. Let's bind Select Weapon to the A button - follow the same steps as above to make the A Button a "Button" type and set Click to "Select Weapon".

Pause/Menu was bound to the Application Menu button on the Vive controller, but there is no such button on Knuckles. So we'll bind that action to the B button.

Shield was on the Grip button on the Vive Controller. The Grip on Knuckles is more capable though, so we need to make sure we get the right value bound to this action. In this case, we want squeezing the grip to activate the shield instead of just closing your hand around the controller. The first step to doing that is to add a "Button" mode. Then click the gear icon to bring up settings for that mode.

From here click on "Generate Click From" to pick where the click comes from. "Force" is the option we want so we're using the force sensor. The other option here is "Pull", which for Knuckles means the capacitive (proximity and touch) sensors on the handle. For some games and actions that's the right choice, but we're looking for a squeeze in our case.

Click "Close" to save this setting. Then set Grip > Button > Click to "Shield".

Now we just need to bind the pose and haptic actions to some values so the game will get reasonable controller positions and send haptic feedback. We are planning to add more functionality here, for now it's simply using the raw pose and the standard haptics of the controller. These settings can be found under "Edit Action Poses" and "Edit Haptics"

For Pose, just set "Left Hand Raw" to "pose" like this:

And for Haptics, set "Left Hand Haptic" to "haptic" like this:

As we've been binding actions on the left hand, those same bindings have been populated on the right hand automatically. This saves us a bunch of work for games with mirrored inputs.

Test your binding

Any changes you make in the binding UI are applied to the game automatically. Just start Jeeboman and pick up your controllers to see how they work.

Sharing the binding with the community

Now that our bindings are good to go, we'll share them with anyone else who wants to use Knuckles to play Jeeboman. To do that just click the "Publish to Workshop" button at the bottom of the binding window.

Give your binding a reasonable name and description, and then click Save to share it.

Once you share your binding it will appear as an option for other users.

And that's it for Jeeboman!
Case Study #2 - Beat Saber
Our second case study of how to rebind a game is Beat Saber. This one only has two actions, so it'll be pretty easy - but there's an exciting twist along the way!

Defining "actions" for Beat Saber

Once again our first step is defining actions for the game. Go to the Setup Legacy Actions tab just like we did for Jeeboman. Then we ask ourselves the same three questions.

Does the game use the controllers interchangeably?

The controllers in Beat Saber both do the same thing. One happens to be red and the other blue, but the buttons and what they do are the same on each controller. So we check the "This game expects the left and eight hands to use the same actions" box.

What simple "actions" does the game have?

There are only two things you can do in Beat Saber (apart from slicing blocks apart): The trigger button selects things from the menu, and once you're in a song the application menu button pauses and brings up a menu. So we'll name those two actions and hide everything else.

That gives us these actions:

What complex or "Simulated" actions does the game have?

None that we know of. It's just menu clicks and trigger clicks. Or is it...? Keep reading to find out more!

Binding actions to the new controller

We'll put the Select action on the trigger with a button mode, and the pause/menu button on the B button with another button mode. Don't forget to also also bind our pose to Left Hand Raw and our haptic to Left Hand Haptic (under the Edit Action Poses and Edit Haptics buttons). At this point our bindings look like this:

Testing Bindings

We're all done, but before we publish our bindings we'd better make sure they work.


And they don't! Oh no!

There are two problems with things as we've bound them:
  1. The trigger doesn't count as "any button" when dismissing the warning text that comes up when the game starts. (For that matter neither do any of the other "any buttons" on the controller.)
  2. The trigger doesn't activate any of the menus, so there's no way to get into a song.

Let's take those one at a time.

The "any" button

When Beat Saber launches it shows a safety warning that claims it can be dismissed by "any" button. The trigger doesn't work, though, so we'll need to make another button do that job. Fortunately there are a bunch to choose from.

First, we need to get back one of our other buttons. In this case let's use the trackpad press as our "any button" and then bind that to anywhere we want to dismiss the dialog. (The game doesn't use trackpad press anywhere other than dismissing that warning so we can go crazy with the bindings if we want lots of stuff to be able to dismiss the warning.)

To do that we need to unhide the trackpad press action. Go back to the "Set Up Legacy Actions" tab. "Show Hidden Actions" is the button we're looking for - the dialog that pops up will show all the previously hidden actions:

Find Trackpad / Thumbstick Press and click Show". Close out of this dialog, and let's name this action the "Any Button":

Then go back to the "Legacy Bindings" tab and go crazy binding it everywhere:

We test again and find that any of the inputs bound will now dismiss the warning.

Making the trigger work

To make the trigger work we'll need to employ one of the secret bits of inside knowledge you get from making many binding files for many games: Some games don't use the trigger "clicked" bit, but instead look at the analog value for the trigger and apply some threshold to that to determine if the user has activated the trigger.

There's nothing wrong with a game doing this, it's just a different way of dealing with a trigger. The Vive Controller and Knuckles are relatively unusual for even having a click at the end of the trigger. Oculus Touch, Windows MR, and Xbox 360 controllers only have the analog value to work with.

It turns out that Beat Saber is such a game. Unfortunately the only way to tell that a game is using a trigger this way is to try to use "trigger pressed" and find that it doesn't work.

Fortunately this is easy to fix with Simulated Actions. In this case, a Simulated Trigger Pull action. First we go back to Setup Legacy Actions and click the Add Action button under Simulated Actions.

Then we pick Simulated Trigger Pull since we want to cause the trigger to be pulled:

This action defaults to "None" - click on this "None" button to bring up the selection dialog. We want the "Trigger Value" option since it's the primary trigger we want to simulate.

Then we hide our old and busted select action, name our new Simulated Action "Select", and end up with this list of actions:

Now we can go back to the bindings tab to make the Trigger use the new Select action:

Sharing the binding with the community

Now that we've created an Any button, and changed the Select action to use a simulated trigger pull, we can play Beat Saber with no issues. We're able to get to the menu, select a song, pause, etc. Time to come up with a reasonable name and description and publish the binding.

Case Study #3 - Moss
Our third and final rebinding case study is Moss. Moss adds some curveballs that our other case studies didn't have, so it's a good example of how to rebind a game with a more complex input scheme.

Defining "actions" for the game

Fortunately the folks at Polyarc provide a controller layout that we can use as a guide.

Based on the diagram it looks like our set of actions will be:
  • Grab - both controller triggers
  • Menu/Recenter - both controller Application Menu buttons
  • Move - left trackpad
  • Attack - click on left side of right trackpad
  • Jump - click on right side of right trackpad
  • Aim - Touch the right trackpad
  • Aim Direction - touch on right trackpad

When you get into the game and use the menu, you'll also find that these actions exist:
  • Menu Up - Click top of trackpad
  • Menu Down - Click bottom of trackpad
  • Menu Confirm - Click right side of trackpad
  • Menu Back - Click left side of trackpad

Does the game use the controllers interchangeably?

Definitely not. Each controller has different functions with the menu button being the only point of overlap. As a result we'll leave the "This game expects the left and right hands to use the same actions" checkbox unchecked and bind the hands independely.

What simple "actions" does the game have?

Some of the actions are simple and we can just rename them:
  • Left Grab
  • Right Grab
  • Menu/Recenter
  • Move Direction
  • Move
  • Aim
  • Aim Direction

So we rename these actions and hide the rest of simple actions.

What complex or "Simulated" actions does the game have?

This is where things get more involved. Moss uses trackpad clicks for Attack, Jump, Menu Up, Menu Down, Menu Confirm, and Menu Back. We'll need to create a Simulated Trackpad Click action for each of those. To do this, click Add Action and select Simulated Trackpad Click from the menu.

That results in a new simulated trackpad click action on which we can set a name, target trackpad, and click position.

We set the action name in the text box like normal. Then we click on Select Trackpad to pick which trackpad (right or left) should be the target of this simulated action. And finally we set the trackpad position by clicking on the circle wherever the click should occur. If we do that for the Jump action, we get a trackpad action that looks like this:

If we create these for all six trackpad click actions, we'll end up with something like this:

And with that we should be ready to move on to the next step.

Binding actions to the new controller

In addition to being complicated to define actions for, Moss also has enough actions to warrant using the trackpad as multiple buttons. To do that, we will use add a Dpad mode on one of the trackpads. Dpad modes let us bind actions to five slots:
  • North
  • South
  • East
  • West
  • Center

In our case, we want to use the trackpad, the A button, and the B button on the left hand to use the menu. We bind Menu Up to North on the dpad, Menu Down to South on the dpad, Menu Confirm to A, and Menu Back to B.

To move Quill around the game we'll use the left joystick. First we add a Joystick mode to the stick and then bind Move to Touch and Move Direction to Position.

Then we bind Left Grab to the left trigger with a button mode, and the left controller is finished. Because Moss doesn't expect left and right to be the same we now need to bind the rest of the controls to the right controller.

First, we'll bind Right Grab to the right trigger so it matches the left side.

For Jump and Attack, we'll use button modes on the A and B buttons. We picked A for jump because it is a little easier to get to on the controller, and Jump is a more common action in the game. Some users might prefer the reverse and are it would be easy for these two actions to be rebound now that everything is named.

To bring up the menu, we'll use the right trackpad as one big button. FIrst we add a button mode to the trackpad and then bind that to our Menu/Recenter action. Ideally this action would have been on the left hand too, but unfortunately we ran out of buttons over there so we'll use the right trackpad instead. One feature that legacy games can't access is telling SteamVR which actions are active when the game is in different states (like having a menu up) so we end up needing to keep all actions bound at the same time. That can lead to using more buttons than might be strictly necessary.

The last actions we need to bind are Aim and Aim Direction. These cause the fire beetles to aim and shoot once you get a little further into the game. We want to put these on the right joystick with another Joystick mode. We'll bind Aim to Touch on that mode, and Aim Direction to Position.

Our final bindings look like this:

Testing our bindings

Because this is a guide and we were able to debug things before writing the guide, everything works great!

In reality, constructing a binding for a game as complex as Moss took some iteration. Don't be surprised if you have to go back and forth a bit before you're happy with the results.

Sharing the binding with the community

Now that we're happy with our bindings, we'll share them with the community with the Publish to Workshop button. This is especially useful for a game with a more complex input scheme like Moss. Even if somebody doesn't like our particular choices for what is bound to what they can take advantage of the naming we did for the actions and have a head start on their own rebinding.

This concludes our three case studies, and with them our guide for how to rebind legacy games to new controllers. Hopefully this has been a helpful overview, and will get you started rebinding things on your own. All three case studies are shared publicly as examples if you want to look at them in detail.

We started in each case by generating a list of actions that was expected by each game, giving those actions reasonable names, and hiding everything we didn't need. This step is important because it makes the rest of the process much easier, and helps the UI to make more sense.

Our second step in each case was to bind those actions to inputs on whatever controller we were using. All three examples used Knuckles as the example controller, but the process is largely the same for any controller.

Third, we tested out our new bindings by playing them in the actual game. Because the game's bindings are updated live with each change, we can do all of our testing and iterating without ever quitting the game. In these examples the "testing" went pretty smoothly, but often some back and forth between defining actions, binding those actions, and testing is necessary to make everything work. Don't be discouraged if your binding doesn't work exactly right the first time.

And finally, we published each of our examples on the Steam Workshop for anyone to use. This isn't strictly necessary, but other SteamVR users with your specific controller would appreciate your efforts.

Please let us know if this has been helpful to you in the comments. We'd also like to hear about any trouble you run into with your own bindings. The SteamVR Input system is pretty new, and we are always happy to hear feedback that would help us to make it better.
< >
FunkeymonkeyTTR Jun 12 @ 12:32pm 
forgot to mention the most annoying problem with this menu, almost every game I try rebind has a bunch of "actions" that just aren't used by my controllers, however these actions appear in orange at the top and the menu WILL NOT let me save my bindings until I've placed all these useless actions somewhere... I just tweaked some bindings for a game that had 16! unused actions, I was forced to bind all of these to something just to get my changes to save.

I also believe that blocks you from reverting to default if you catastrophically mess the bindings up since the default is in an unsaveable state, I remember once having to download a game on a 2nd pc to steal the bindings file cause I couldn't get the default back.
FunkeymonkeyTTR Jun 10 @ 11:34am 
This menu really needs to be updated, developers are absolutely terrible at converting bindings from different headsets, 2 years later and I still never found a way to solve this issue in my comment a little below this one...

its much worse now developers can label "actions" it seems to completely remove the option to add legacy bindings, so 99% of the time a developer forgets to add a conversion as usual and I can't even manually add it
spafmagic Dec 26, 2021 @ 10:30pm 
WALL OF TEXT! I don't read very fast and my eyes started to strain less than half way down.

I don't blame the author of this guide, but could this process be any more COMPLICATED??

Are VR controllers so different than a joy/flight stick, that the SteamVR Controll binding editor can't SIMPLY have a list of functions like NORMAL games do... where you can just click on the function (like "Menu") to make it watch for a button press, press a button like Y, and be assigned to the button pressed?

When remapping buttons... it should be as simple as that! This... is like going around your elbow to get to your rear end!
FunkeymonkeyTTR Feb 6, 2021 @ 6:25pm 
where is the B button in any of these settings? I'm trying to get a game working on the Vive wands that only supports rift and index bindings, it only uses 2 buttons the A and X or B and Y call me stupid but how do I set these 2 buttons onto the vive wand?
ree3 Dec 13, 2020 @ 3:08pm 
How to import ?
Barba-Q Oct 31, 2020 @ 12:47am 
Is it possible to invert some inputs? Like release to be trigger click?
Akuxray Jul 5, 2020 @ 5:30pm 
It is posible to change the teletransportation mode to a fluid mode at the joystick movement(left joystic)?
Memz Jul 1, 2020 @ 5:49pm 
I'm trying to rebind VRChat to have a more Oculus Touch-esque control schema, but the simulated actions aren't showing up in the Chords menu, which is proving to be something I need if I want to get close. I'm also having an issue, where I need a simulated action to be a Trackpad touch, not a click, and I can't seem to figure that out. If the gesture input clicks, the gesture input cancels and the character begins moving. Am I missing something, or am I trying to do something that Valve didn't think of when implementing Steam Input 2.0 for VR?
Marflemerfmarf Apr 6, 2020 @ 1:31am 
Tink, I had the same issue with the new limited access keyboard that we've been bestowed.
My fix was to bring the controller binding menu up on desktop by starting vr, going into steam vr settings from the vr popup menu, selecting devices, and clicking controller settings.
Tink Mar 9, 2020 @ 12:25pm 
I think something must have changed because there is no way to type anything in when setting legacy actions. There isn't any on screen keyboard and the physical keyboard doesn't work.

Am I missing something?