Alexander

Alexander

hit me up
Home

Input Registrar – Example

Alexander - 09/06/2016

This is my input system. There are many like it, but thi- okay yeah, I made that joke last time.

So when working on Charge the HTC Vive wasn’t out yet and very little had been made for it in Unity beyond tech demos and the example code people were sharing for VR controller input was mostly just button checks in the update loop – classic ‘my first game’ stuff. On top of this most of the good input solutions for Unity are premium, and as good as assets such as Rewired are, sometimes you want to make your own thing which is good enough for you because ‘it’s free’ to do so.

Since Charge I reworked Input Registrar to be more than just a Vive solution that can easily be expanded for different controllers, easy input rebinding, multiple players etc. I’m gonna start with showing a simple example of how to use Input Registrar with the HTC Vive to add some basic shooting functionality. The following script would be added to both of the Controller GameObjects which are part of the SteamVR CameraRig prefab.

using InputRegistrar;

[RequireComponent(typeof(SteamVR_TrackedObject))]
public class ViveController : MonoBehaviour
{
    SteamVR_TrackedObject trackedObject;

    [SerializeField]
    InputManager inputManager;

    void Start()
    {
        trackedObject = GetComponent<SteamVR_TrackedObject>();

        Initialise();
    }

    public void Initialise()
    {
        inputManager.Initialise((int)trackedObject.index);
        inputManager.RegisterButtonInput(new ButtonGesture(InputValue.Beta, ButtonAction.OnPressDown), Shoot);
        inputManager.RegisterAxisInput(new AxisGesture(InputValue.Beta, AxisAction.GetAxis), TriggerHeld);
    }

    void Update()
    {
        inputManager.Update();
    }

    void Shoot()
    {
        inputManager.VibrateController(0.8f);

        Ray raycast = new Ray(transform.position, transform.forward);
        RaycastHit hit;
        bool bHit = Physics.Raycast(raycast, out hit, 50f);
        if (bHit)
        {
            Rigidbody rb = hit.collider.GetComponent<Rigidbody>();
            if(rb)
                rb.AddForceAtPosition(transform.forward * 50f, hit.point, ForceMode.Impulse);
        }
    }

    void TriggerHeld(float _value)
    {
        print("Trigger squeeze amount: " + _value);
    }
}

Firstly, and most importantly, we need an InputManager (in the InputRegistrar namespace, not the Unity one) which is a serializable non mono class. This can either be serialized allowing us to set the InputMethod in the inspector (in this case Vive, but could also be Xbox controller, keyboard etc), or an instance can be created in code.

As this is a Vive input script we need a variable for the SteamVR_TrackedObject because we need a way to differentiate which controller we want to get the input from, which is done by passing the controller index to the input manager on line 20 (highlighted).

Now we want to register all the inputs which in this case is just two, one ButtonInput and one AxisInput. The process is essentially the same but differentiating between a button and an axis allows us to clearly define if we want to return a value or not; see how TriggerHeld expects a float while Shoot does not even though both apply to the same input (InputValue.Beta, explained below). There is also a third case for DoubleAxisInput which expects a Vector2 which for the Vive controller is only applicable for the touchpad.

To specify what InputGesture we want to map a method to we pass a gesture to RegisterInput – where a gesture is a combination of an InputValue and an InputAction. The InputValue is the shortcode for the button or axis on the controller, e.g. for the Vive alpha is the touchpad, beta is the trigger, gamma is the grip buttons and delta is the application menu button. I use the greek alphabet as a layer between the input and output (see Command Pattern) which allows for easy remapping, controller swapping etc. Say I want to swap from a PS4 controller to an Xbox One controller in a PC game then all I need to do is unregister the current PS4 registrar and register an Xbox registrar without having to worry about how each input maps on the new controller. Finally the InputAction is the action we want to check the specified input for, in this case OnPressDown is the first instance a button is pressed down and GetAxis will call the associated method whenever an axis is not zero.

This has been a quick look into Input Registrar and hopefully I’ll get round to sharing more of the how it works code soon.

Leave a Comment


Leave a Reply

Your email address will not be published. Required fields are marked *


Alexander Dudok de Wit

http://onf.re/