Immerseum SDK: VR Simulator (version: BETA-0.9)
      [view as: Desktop | Tablet | Mobile]
Custom Input Handling
In This Topic

While the VRSimulator handles most basic movement for you out of the box, there are interactions specific to your VR experience that (obviously) we can't foresee. There might be many situations in which you want your VR experience to react to your user's actions (inputs) beyond simple movement:

You can do all of this and more using Custom Input Handling, which lets your code listen for our Input Action Events and then respond accordingly.

Input System Overview

The way movement works in any VR experience (or computer game, etc.) is really straightforward:

 

The software needs to receive (capture) the user's input from whatever device was used. Based on the input received (what button was pressed, what thumbstick was moved, etc.) the system needs to decide what that input means ("Move the player forward", "Fire the blaster cannon", etc.). And once that decision is made, the system needs to respond and do whatever it should do ("Move the player one step forward", "Start the process of firing the blaster cannon").

Where this can get complicated is that most input devices are built and designed differently, have different hardware features, different drivers, etc. And different experiences (and even different users within the same experience!) may want to have different button layouts, controller configurations, etc. for their style of play. Trying to accommodate all of the variability that's out there can get very complicated, very fast.

Which is why we have broken this process into four key concepts:

 

Important Things to Know

Listening for an InputAction Event

The key to custom input handling is for your methods to "listen" for an InputAction Event.  A method that is listening for (subscribed to) an InputAction Event will always execute whenever that InputAction Event is fired. Below is a sample of a custom InputAction listener method:

public class myCustomClass : MonoBehaviour {
   void OnEnable() {
      // "Listen" for the Input Action.
      EventManager.OnInputActionStart += myCustomListener;
   }

   void OnDisable() {
      // "Unlisten" for the Input Action.
      EventManager.OnInputActionStart -= myCustomListener;
   }

   void myCustomListener(InputAction firedAction) {
      if (firedAction.name == "DesiredInputAction") {
         // Do something (or call another method) here.
      }
   }
}

In the code above, the OnEnable() method is where you set myCustomListener to "listen" for the event EventManager.OnInputActionStart to occur.  Essentially, what you're doing is adding the method myCustomListener to a list of methods that will be called whenever OnInputActionStart occurs.

Best Practice Best Practice

To make our code easier to follow / keep straight, we always name our listener methods the same as the event they're listening to.

Thus, we wouldn't actually use myCustomListener but instead OnInputActionStart. Of course, you can use whatever naming conventions you like, but this one works well for us.

The OnDisable() method is where you then remove the myCustomListener method from the list of methods listening for OnInputActionStart. This is to prevent memory leaks - if you didn't "unlisten", then even when you closed Unity, shut down your game, and went off to get a cup of coffee there would still be a lonely little bit of software somewhere waiting in vain for the OnInputActionStart event to occur. That's a textbook definition of a nasty memory leak problem.

Reacting to the InputAction

The sample code above contains a method called myCustomListener which is a good example of reacting to the Input Action. Here is that code again, just so we can go over its important parts:

void myCustomListener(InputAction firedAction) {
   if (firedAction.name == "DesiredInputAction") {
      // Do something (or call another method) here.
   }
}

First, please notice the return type and parameters for the method. Every single method that listens for the OnInputActionStart event must have the same return type (void) and the same parameters (a single InputAction object).

Be Careful! Be Careful!
If your custom listener for the OnInputActionStart event does not have a return type of void and accept a single InputAction parameter, your code will throw an exception.

Second, notice the if { ... } statement inside of the myCustomListener method. This myCustomListener method will execute whenever any InputAction is detected, regardless of what that InputAction actually represents. But presumably, you want your myCustomListener to only respond to a particular InputAction (a primary trigger pull, for example). This if { ... } statement makes sure your code is only executed for the specific InputAction(s) that you want - in the example above, an InputAction named "DesiredInputAction".

And that's it! There you have a custom input handler.

Best Practice Best Practice

If you're using our default InputActions but wish to create custom handlers for them, there is an easier way: Each of our default InputActions has its own InputAction-specific events which get fired whenever the InputAction is detected.

This allows you to listen for a specific InputAction without checking its name property as shown above.

For more information on the events fired by our default Input Actions, please see the Default Input Actions reference.

Customizing Movement

There are three ways to customize the VRSimulator's movement logic:

  1. Retain our default Input Actions and just replace our movement logic,
  2. Use your own Input Actions, but keep Immerseum's default movement logic,
  3. Use your own Input Actions and your own movement logic.

Retaining Immerseum Input Actions with Custom Movement

If you wish to retain our default Input Actions while customizing movement, you need to do the following:

  1. Turn off Default Input Map in the MovementManager's settings.
  2. Write a custom listener for each of the default Input Actions you wish to support.

The best (easiest to understand and most-performative) way to do this is to use one "switchboard" method as in the example below:

void OnEnable() {
   EventManager.OnInputActionStart += myCustomSwitchboard;
}

void OnDisable() {
   EventManager.OnInputActionStart -= myCustomSwitchboard;
}

void myCustomSwitchboard(InputAction firedAction) {
   switch (firedAction.name) {
      case "togglePauseMenu":
         // ... Custom Code Here
          break;
      case "toggleView":
          // ... Custom Code Here
          break;
      case "togglePrimaryTrigger":
          // ... Custom Code Here
          break;
      case "toggleSecondaryTrigger":
          // ... Custom Code Here
          break;
      case "toggleRightThumbstickClick":
          // ... Custom Code Here
          break;
      case "toggleLeftThumbstickClick":
          // ... Custom Code Here
          break;
      case "toggleRightBumper":
          // ... Custom Code Here
          break;
      case "toggleLeftBumper":
          // ... Custom Code Here
          break;
      case "toggleSelectionButton":
          // ... Custom Code Here
          break;
      case "toggleCancelButton":
          // ... Custom Code Here
          break;
      case "toggleSecondaryButton":
          // ... Custom Code Here
          break;
      case "toggleTertiaryButton":
          // ... Custom Code Here
          break;
      case "xAxisMovement":
          // ... Custom Code Here
          break;
      case "zAxisMovement":
          // ... Custom Code Here
          break;
      case "pitchRotation":
          // ... Custom Code Here
          break;
      case "yawRotation":
          // ... Custom Code Here
          break;
   }
}

Given the code above, just replace the comments // ... Custom Code Here with your own method calls, and you'll have successfully rewired our movement system.

Using Custom Input Actions with Default Movement

If you wish to use your own custom Input Actions but retain all of Immerseum's movement logic, you should:

  1. Turn off Use Immerseum Defaults in the InputActionManager's settings.
  2. Define your own custom InputActions with the same names as our default InputActions.
  3. At runtime, register your custom InputActions with the InputActionManager as described in Custom InputAction Mapping when the EventManager.OnInitializeInputActions fires.

And that's it! Now the VRSimulator movement system will move the user in response to your custom InputActions. For more information, please see Replacing Default InputActions.

Using Custom Input Actions with Custom Movement

If you wish to use your own custom Input Actions with your own custom movement logic, you should:

  1. Turn off Default Input Map in the MovementManager's settings.
  2. Turn off Use Immerseum Defaults in the InputActionManager's settings.
  3. Define your own custom InputActions. In this case, you can use whatever names you want.
  4. Write a custom listener or a switchboard listener for each of the custom InputActions you wish to support.
  5. At runtime, register your custom InputActions with the InputActionManager as described in Custom InputAction Mapping when the EventManager.OnInitializeInputActions fires.

And that's it! Your InputActions will now result in whatever movement you've defined through your custom listeners.

See Also

Configuring the VRSimulator

Scripting Reference

 

 


2016 Copyright © Immerseum Inc. All rights reserved.

Send Feedback