ValveSoftware/unity-xr-plugin

Unity XR Input / Unity Input System not working

hollowworldgames opened this issue Β· 116 comments

While I do get hand positions and controllers all the buttons are false or 0. I am using Unity 2020.1 16b and beta 7. I am testing with an htc vive with wand controllers, and STEAMVR 1.13.10.

zite commented

Unfortunately we were unable to find a good compromise between the Unity Input System and OpenVR (legacy input). Additionally, further work on that front is prolonging access to OpenXR. This means Unity XR Input (or Unity Input System) will not work with this OpenVR plugin. We're now directing our efforts towards OpenXR. You can read more about this decision in general here: https://store.steampowered.com/newshub/app/250820/view/2522527900755718763

@zite So does that mean the will be a future version of this or another plugin that will support Input via OpenXR which will work with the Unity XR Input?

It's nice having a single input system that works for Oculus, WMR and PSVR. We used to use VRTK to facilitate input across the various platforms, but that is no longer a viable solution.

zite commented

A single input system is definitely the goal. We'll either support or work on a plugin that enables vr developers to target one cross platform api. But, it won't be in this plugin.

@zite what do you mean it won't be in this plugin? isn't the whole purpose of this plugin to support the Unity XR Tech Stack (https://docs.unity3d.com/Manual/XRPluginArchitecture.html)? What's the purpose of having this plugin if that doesn't work? The XR Interaction Toolkit also depends on the Input subsystem, so it won't be working if the Input subsystem doesn't.

Am I understanding this correctly: There's nothing at the moment that will let me use an Valve Index with Unity 2020.1?

zite commented

Am I understanding this correctly: There's nothing at the moment that will let me use an Valve Index with Unity 2020.1?

SteamVR works great with the normal SteamVR Unity Plugin (that adds this plugin automatically). You'll need to use the beta here for now though: https://github.com/ValveSoftware/steamvr_unity_plugin/releases/tag/2.6.0b3

Cool, Thanks!

zite commented

@zite what do you mean it won't be in this plugin? isn't the whole purpose of this plugin to support the Unity XR Tech Stack (https://docs.unity3d.com/Manual/XRPluginArchitecture.html)? What's the purpose of having this plugin if that doesn't work? The XR Interaction Toolkit also depends on the Input subsystem, so it won't be working if the Input subsystem doesn't.

We're handling input through our own plugin while we work with Unity on a solution to get their input system working with modern input standards (OpenVR / OpenXR).

@zite so how do you suggest the XR Interaction Toolkit should be used if that depends on Unity Input?

I found that the XR Interaction Toolkit works with SteamVR on Unity 2019.4, it still has legacy VR support. (Don't install any OpenVR plugins, just tell Unity in Project Settings you want OpenVR support.) It won't work on Unity 2020.1 because that requires the new OpenXR. But assuming the OpenXR ends up getting updated, you can just develope on 2019.4 for now and upgrade when it's available.

@kendrome but can you still use XR Plugin Management then to target other platforms? otherwise there would be no point in using the XR Interaction Toolkit, no?

I wanna add: This is a huge mess. As I understand OpenXR doesn't even have the device plugin interface yet (so what's the point without it?). Why always deprecating an unfinished solution while the next one is still not yet ready instead of once finishing a thing?

@zite OpenVR is supposed to be a superset of what the unity plugin architecture provides right? On the previous repo input was almost working. I'm not saying to postpone OpenXR but a lot of developers with titles on the market right now could double their reach instantly if basic controller support was provided. And players could enjoy more games. Later on you can probably switch them transparently to OpenXR via the unity plugin. It may be a little more work and seem redundant to you but it will be beneficial for many so It's a worthy cause imho

@zite OpenVR is supposed to be a superset of what the unity plugin architecture provides right? On the previous repo input was almost working. I'm not saying to postpone OpenXR but a lot of developers with titles on the market right now could double their reach instantly if basic controller support was provided. And players could enjoy more games. Later on you can probably switch them transparently to OpenXR via the unity plugin. It may be a little more work and seem redundant to you but it will be beneficial for many so It's a worthy cause imho

I second that, especially since it was working fine before splitting the repository out from the steamvr_unity_plugin.git#UnityXRPlugin branch (at least for VIVE that is). Canβ€˜t you just re-add the same kind of controller input that you had working before splitting the code into its own repository? We use the OpenVR plugin only to target the VIVE and I understand that maybe other OpenVR compatible devices donβ€˜t map the input well - but the Quest and the Vive are the two most important headsets to target and it must be possible to use the Unity XR Plugin architecture to target them both. This is more important than having all possible OpenVR compatible devices map their input well (important too for the future, agreed, but donβ€˜t remove a feature that was working well for the most important device class just because it doesnβ€˜t work optimally yet for less important ones)

Actually if you just made sure that this plugin works with the vives and the index we have full coverage along with the existing oculus and wmr plugins. Sure it won't be the ideal but right now VR is still a developing market and we need all the reach we can get. We are also mostly indies doing it and short of resources. I'm sorry to be blunt but at this point giving us something crude to work with is more important than standards. I dare to say that the livelihood of small studios is at stake here

I found that the XR Interaction Toolkit works with SteamVR on Unity 2019.4, it still has legacy VR support. (Don't install any OpenVR plugins, just tell Unity in Project Settings you want OpenVR support.) It won't work on Unity 2020.1 because that requires the new OpenXR. But assuming the OpenXR ends up getting updated, you can just develope on 2019.4 for now and upgrade when it's available.

Just to confirm, with this you do not need XR management + Valve XR plugin either? @kendrome

I found that the XR Interaction Toolkit works with SteamVR on Unity 2019.4, it still has legacy VR support. (Don't install any OpenVR plugins, just tell Unity in Project Settings you want OpenVR support.) It won't work on Unity 2020.1 because that requires the new OpenXR. But assuming the OpenXR ends up getting updated, you can just develope on 2019.4 for now and upgrade when it's available.

Just to confirm, with this you do not need XR management + Valve XR plugin either? @kendrome

It works without the XR plugin from Valve. I'm using the depreciated XR Settings under Player Settings. I'm able to use the XR Interaction Toolkit with both SteamVR and Oculus in the same project. It looks like when you enable OpenVR it installs the OpenVR Desktop plugin from Unity, so doesn't really use OpenXR, but should provide a direct upgrade.

Seems to me like this stance is the exact opposite of wanting to support the OpenXR standard. Instead you want to change the standard to fit your own legacy system. And in the mean time you leave everyone with no choice but to put in a bunch of extra work to support your legacy system, a choice which is made even harder by not providing any ETA on when yet another change to the input system might happen. And the whole situation is even worse for those of us who already started using this OpenXR plugin for input when it was first working, only to have it pulled later.

@halfpasttense Just to set the record straight I think there's some confusion here:

The unity XR plugin architecture has nothing to do with OpenXR and open standards. It is a strictly unity thing, a good option to have in my opinion.

OpenXR is essentially the steamvr architecture made into a standard. I had to use it to get full coverage of hmds on steam and I can now say that it's good.

That being said, right now I have to maintain two different projects. One for oculus and one for steam. There's just no way that the middlewares from both can coexist. If someone has managed to do it I'd love to hear how.

It's not a good situation for developers right now, but at least OpenXR is coming to ease things up.

In the meantime, it would certainly be feasible to implement the full unity xr functionality on top of SteamVR which IS a superset. I think the main problem the devs encountered and made them decide to go half way was the disparity of the anchor of the action poses. There were some issues where hands in the virtual world would seem displaced. Unity seems to be utilizing what SteamVR calls the "tip" or "raw" pose/anchor by default. For my project the "grip" pose made more sense for controlling hands so in steam I use that and correct for oculus.

Still, I think it would certainly be possible to craft an actionset and bindings in SteamVR to handle the most common controllers and provide an adequate solution for now. Standards are good when they help shipping projects faster and better. And right now OpenXR cannot help with that, maybe in some months but we don't all have the luxury of waiting it

@wizgrav ah, I see. I thought The Unity XR Plugin system was Unity implementing the OpenXR standard from the engine side, but it appears I was mistaken. Regardless, not supporting the XR Plugin system for controller input is still a giant pain in the ass right now.

Your explanation of why they may have chosen not to support it doesn't make sense to me. What do action poses have to do with simply getting the damn inputs off controllers? I don't even care about action poses. Also, they DO provide controller positional tracking data... They just refuse to provide the controller inputs. And also I'll reiterate that they had a version that had controller inputs and it worked fine. In fact I still have that version and am still using it for testing because I haven't had the time or the will to go back to their damn legacy plugin. Unfortunately I can't continue to use this old version of the XR plugin because while it works fine running in the Unity editor, it doesn't work at all when compiled to a standalone app. If they still provided the controller input I could get away with having almost 0 code difference between building for Oculus vs building for SteamVR. As you stated, the only difference is a slight adjustment to the controller placement depending on the platform.

My guess as to why they don't want to support input is because they want developers to adopt the full SteamVR binding system that binds in game actions to inputs, instead of just listening for raw inputs. It's a pretty lame reason, and that choice should be left up to the developers, not forced on them.

Action poses are a rather nifty feature in steamvr where you can tell the middleware to report the rotation/translation for a specific part of the controller like the base or the tip. You could achieve the same with a simple transform of your own but still is a good feature.

In general the transition from steamvr->OpenXR should be pretty straightforward, valve wrote the standard for the most part from what I can tell.

Even though we are on the same page and I feel we are not treated well. I still suggest you to take a little time to use the functionality provided by steamvr for now. You can use the tracked pose driver component for the head and the steamvr plugin provides a SteamVR_behavior_pose which works more or less like the tracked pose driver for the controllers.

For key input you'll need to fiddle a bit with the bindings tool included in steamvr. From the code side you get simple getters to check the state of buttons and some niceties like being able to tell to joysticks to report like dpads which saves you the trouble of parsing the analog values yourself(if you actually need them to behave like that and not that it would be that hard to do manually but it's a nice feature nevertheless) It's not a big hassle overall, if you need help feel free to pm me. I have to warn you though that I haven't yet managed to have a single project that produces builds for both oculus and steam so I suggest you to do the same split

That being said, right now I have to maintain two different projects. One for oculus and one for steam. There's just no way that the middlewares from both can coexist. If someone has managed to do it I'd love to hear how.
@wizgrav

I've never had a problem with them co-existing, what kind of trouble are you having that forces the two projects? The only thing I have to do is when building for Oculus is to exclude the SteamVR dlls that I use for Steamworks. If I didn't use Steamworks then same build works for submitting to both Steam and Oculus. With the Unity XR Input it's easier than it used to be when I had to rely on VRTK. The platform specific code is really minimal now. The only thing is I have to stay on Unity 2019 until Valve updates the plug-in to support XR input.

The steamworks stuff is ok, I also use them and do the same, delete the steam dlls so oculus can accept the build. The combination of the new unity XR plugin from steam along with the steamvr plugin don't play well with other things. In fact I had to start a project from scratch, install all the steam stuff first, disable the autoupdating of the unity xr steam plugin and then import the rest of the game in. Anything else was creating problems. 2020 I tried and it's even more problematic, I will definitely stay away from it for a bit longer. Tbh maybe these were hiccups in earlier versions of the steamvr middleware but now I resorted to that split project approach and I can at least produce builds for all my targets. Ideally I would also prefer to just toggle the appropriate plugin in the unity xr management and not have to do anything else. I am pragmatic though and I don't think we will get that option anytime soon

@wizgrav I have no intention to use any of the functionality provided by the SteamVR plugin. It's all fluff that I don't need. Literally all I need is the raw controller inputs. I already have solutions for everything else in a non-platform specific way. I have half a mind to try to fork this plugin and add input support myself.

@kendrome

The only thing is I have to stay on Unity 2019 until Valve updates the plug-in to support XR input.

Um this entire conversation has been about Valve's refusal to support XR input with this plugin. So don't hold your breath. Unless you mean OpenXR support, which who knows how long that is going to take both from the Unity side and Valve side.

Um this entire conversation has been about Valve's refusal to support XR input with this plugin.
@halfpasttense

Valve has already said they would support it, just not in this plug-in.

A single input system is definitely the goal. We'll either support or work on a plugin that enables vr developers to target one cross platform api. But, it won't be in this plugin.

@kendrome Right. But "just not this plug-in" is the important part. Even this plugin is still in beta. Who knows how long it will be before something else comes along. And on top of that, whatever they do decide to support obviously won't be the Unity XR input system which everyone is already using, so even if "a single input system is definitely the goal", whatever that turns out to be will require all of us developers to again switch everything over to a whole new system.

What is everyone doing while we wait for this to get solved? Does anyone have any clever ideas, I sure could use one.

Also do we have a clue when this all might get resolved, time frame, months, a year?

Use 2019.4 and the legacy VR stuff and it works for now. Then when the OpenXR input system from Valve is completed you can upgrade and continue to use the Unity XR Input system as you've been using it in 2019.4.

Use 2019.4 and the legacy VR stuff and it works for now. Then when the OpenXR input system from Valve is completed you can upgrade and continue to use the Unity XR Input system as you've been using it in 2019.4.

What do you mean by legacy VR stuff, not use XR management and use something like SteamVR or Oculus Plugin (the suite, not the xr plugin) or do you mean the legacy input with XR Management +SteamVR XR plugin ?

I would like to use SteamVR but once I publish on steam store, I always run into controller issues because of manifests, some one will complain saying their controller does not work. Probably I am doing something wrong but, I am trying to avoid having too many points of failures and places I would have to troubleshoot. Thanks!

For me there is no option but to go forward and implement steam input with xr management. Frankly, they have left us little choice as new controllers or controllers not supported by xrinput will not be mappable as they are with steam input. Also I understand the buttons on the knuckles are incorrect in legacy anyway. Even legacy with steamvr input is not possible as the steam vr plugin seems to override the far clipping plane to 40k which won't work for a flight sim.

@flightCrazed sorry my bad, by legacy I meant to use the unity XR system for the camera, via the tracked pose driver, and the new steamvr plugin for the controllers

What kind of issues you have with the controllers? You should make sure that you select the correct action pose in the ui bindings tool steamvr provides. In my case I has fists on screen so the best choice was the "Grip" pose. The default (Raw) had as reference the tip of the controller which wasn't ideal and also varied alot between controllers. The "Grip" pose is solid, if you control hands at least

We have been using XR System for the camera rig and activate SteamVR objects when the player has a Vive headset and XR Managerment objects when they have Oculus. We are itching to get rid of the SteamVR stuff but it is needed for this plugin to work. If this isn't resolved soon we will probably stop support for Vive, as most our users are using Oculus anyways.

What kind of issues you have with the controllers? You should make sure that you select the correct action pose in the ui bindings tool steamvr provides. In my case I has fists on screen so the best choice was the "Grip" pose. The default (Raw) had as reference the tip of the controller which wasn't ideal and also varied alot between controllers. The "Grip" pose is solid, if you control hands at least

Thanks, I think it might be some setting in the Steamworks page. When I ran the game via the right manifest doesn't seem to get loaded up and people complain (and happened to me several times) that the controllers do not show up and unable to edit the bindings even. I have to check again, it was a while ago and I don't remember now.

@ary1111 @hollowworldgames

I didn't realize you can use XR management and Steam VR at the same time. I thought Steam VR would take over. I will create a wrapper for the input stuff so I can easily point to the new input, if and when this issue gets resolved. Thank you!

@wizgrav

@flightCrazed sorry my bad, by legacy I meant to use the unity XR system for the camera, via the tracked pose driver, and the new steamvr plugin for the controllers

Just to clarify, I install SteamVR plugin from the asset store, then I install the Open VR XR plugin and enable that. What else do I need for the input to work, which component drives the input from VR. Do I need something in the scene to initialize etc..?

I know how to use the input from VR plugin, this what I used before. But I don't seem to get any reads from the controllers.

@wizgrav

@flightCrazed sorry my bad, by legacy I meant to use the unity XR system for the camera, via the tracked pose driver, and the new steamvr plugin for the controllers

Just to clarify, I install SteamVR plugin from the asset store, then I install the Open VR XR plugin and enable that. What else do I need for the input to work, which component drives the input from VR. Do I need something in the scene to initialize etc..?

I know how to use the input from VR plugin, this what I used before. But I don't seem to get any reads from the controllers.

On your XR Rig game object, add the Player component from the Valve.VR.InteractionSystem namespace. Then I would drag a Player prefab from the SteamVR assets into your scene and add the components you need from that as children of the Camera Offset game object that is a child of the XR Rig. Most of the objects can just be empty game objects to fill the space or completely ignored. The ones you will need for interactions are the LeftHand and RightHand game objects. The only ones I end up having are SteamVRObjects, NoSteamFallbackObjects and HeadCollider. I also added a Teleporting game object to the Rig for that functionality.

@flightCrazed the SteamVR_Behaviour_Pose component is the equivalent of the tracked pose driver for the controllers. You attach it on a gameobject and it will update it's transform automatically. For button input you'll need to fiddle with the UI binding tool and write your own code here's a snippet from mine:

using System.Collections.Generic;
using UnityEngine;
using Valve.VR;

public class SteamWatcher : MonoBehaviour
{
    public SteamVR_Action_Boolean Trigger;
    public SteamVR_Action_Boolean Menu;
    public SteamVR_Action_Boolean Grip;
    public SteamVR_Action_Boolean Up;
    public SteamVR_Action_Boolean Down;
    public SteamVR_Action_Boolean Left;
    public SteamVR_Action_Boolean Right;

    public SteamVR_Action_Vibration Vibration;
    
    private void Awake()
    {
        App.onHaptics += onHaptics;
    }

    void onHaptics(bool isLeft, float strength) {
        Vibration.Execute(0,App.getBuz(),10f, strength, isLeft ? leftHand : rightHand);
    }
   
    
    void Update()
    {
        
     
        bool ls = Left.GetState(SteamVR_Input_Sources.Any);
        bool rs = Right.GetState(SteamVR_Input_Sources.Any);
        bool us = Up.GetState(SteamVR_Input_Sources.Any);
        bool ds = Down.GetState(SteamVR_Input_Sources.Any);
        
    }

}

You then can assign the actions you have configured in the unity steamvr popup(Unity will pick them up after you do the "generate code" step in the steamvr plugin)

If you make a custom action set: don't. Only the default set works so modify that instead and remember to include the Pose in the properties, otherwise the rotation/translation on the controllers won't be updated

Also remember to "replace defaults" in the UI bindings tool to include the manifest in your build

@wizgrav @ary1111

Thanks guys. I am sorry, I should have been more clearer. This part you mentioned I understand. I was wondering what the absolute minimum you need to utilize Valve's input system, but I think I figured it out.

Absolute minimum you need in your scene for Steam input to work.

Here is an example (see the script below), if anyone else (who are confused by this as I was) wants to use the XR Management with Steam input. This is all you need in the scene to use the Steam/Valve input, nothing else, could be an empty scene for all it cares.

I'd create a separate initializer or manager to handle what controls when (Oculus? use Unity Input, Valve? Initialize SteamVR and use that input etc..).

Here is the extended version with everything you need in the project:

1. Install XR Management via package manager
image

2. Install the Steam XR Plugin (OpenVR Loader) and make sure "Initialize XR on Start up is checked" I had to do this manually for 2019.4 as the SteamVR from asset store did NOT automatically install this plugin. @zite
image

3. Install SteamVR Plugin (from the Unity Asset Store)

4. Create a new Scene

5. Add the XR Rig (or whatever you use for tracking headset and hand/controllers)

6. Attach the script below to anything (eventually, you would want to create a more advance version of this and attach to each controllers, or better yet create a wrapper, I use Scriptable Objects for this that can connect all types of inputs)

7. Make sure you have the bindings properly setup in Steam Input and in Controller bindings UI.
image
image

8. Last but not least, pray to gods of VR & hope that Steam and Unity find a solution to this ASAP!

using UnityEngine;
using Valve.VR;

public class InputTester : MonoBehaviour
{
    public SteamVR_Action_Boolean button;

    private void Start()
    {
        //This is the key, without this inputs won't read
        SteamVR.Initialize();
    }

    private void OnEnable()
    {
        button.onChange += Button_onChange;
        Debug.Log("Subscribed");
    }

    private void OnDisable()
    {
        button.onChange -= Button_onChange;
        Debug.Log("Unsubscribed");
    }

    private void Button_onChange(SteamVR_Action_Boolean fromAction, SteamVR_Input_Sources fromSource, bool newState)
    {
        Debug.Log(fromAction + "State Changed");
    }
}

One last thing...

You do NOT need to enable anything in the legacy settings.
image

@ary1111 activate SteamVR objects when the player has a Vive headset.

Could you please tell me how you are doing this, how you're detecting if its Vive, Oculus or WMR? are you using a function from XR management to do this? thanks

List displays = new List();
InputDevices.GetDevicesWithCharacteristics(InputDeviceCharacteristics.HeadMounted, displays);
if(displays.Count > 0)
{
return displays[0].name;
}

Hah as I was writing a response @hollowworldgames added one. For checking the name this is what I have (following running what @hollowworldgames added).

foreach (var device in displays)
{
if (device.name == "OpenVR Headset(vive_cosmos)")
{
       Debug.Log($"Headset Detected: {device.name}. Activating SteamVR Character and Camera");
       //Activate STEAMVR stuff
       break;
}
else if (device.name == "Oculus Rift")
{
       Debug.Log($"Headset Detected: {device.name}. Activating Oculus Character and Camera");
       //Activate XR Manager stuff
       break;
}

@ary1111 @hollowworldgames Thank you both, really appreciate it!

zite commented

Proly safer to do device.name.StartsWith("OpenVR")

Ok there are some seriously weird things going on when I try to use the bare minimum of the SteamVR plugin just to get input. I've called SteamVR.Initialize() and I'm able to use SteamVR_Behavior_Boolean and such to get inputs. But my entire game comes crawling to a halt as soon as I hit the Steam menu button to bring up the overlay and go back. It's like the game is still paused, the view is still blurred, I can do actions that rely only on controller inputs but some update loops are stopped so weird things happen like things that should drop due to gravity just hang in the air. This whole thing is just a giant pain in the ass. Even if I figure out all these weird things happening I still then have to figure out a replacement for UI interaction for which I was using the XR Interaction system, which completely doesn't work because it can't get simple trigger pull input. Thanks Valve.

Ok I figured it out. It instantiates the "[SteamVR]" prefab with the SteamVR_Renderer behavior on it, which was causing all my issues. I had to change some SteamVR_Settings, which I had completely forgotten about. Turned off "Pause game when dashboard visible" as well as "Lock physics update to render frequency" which was what was causing all my weapons to fire way faster than usual, another stupid bug caused by this switch that I've been scratching my head over for a day. However there's still a bug where if press the SteamVR menu button enough times, leaving and entering the overlay, the game eventually gets stuck in a state where the player view is blurred as if the overlay was still up, but otherwise the game still works and is not paused. Only way to get out of this state is to restart the game.

I commented out the line "SteamVR_Camera.sceneResolutionScale = 0.5f;" in SteamVR_Renderer to fix the blurred view getting stuck.

Ok I figured it out. It instantiates the "[SteamVR]" prefab with the SteamVR_Renderer behavior on it, which was causing all my issues. I had to change some SteamVR_Settings, which I had completely forgotten about. Turned off "Pause game when dashboard visible" as well as "Lock physics update to render frequency" which was what was causing all my weapons to fire way faster than usual, another stupid bug caused by this switch that I've been scratching my head over for a day. However there's still a bug where if press the SteamVR menu button enough times, leaving and entering the overlay, the game eventually gets stuck in a state where the player view is blurred as if the overlay was still up, but otherwise the game still works and is not paused. Only way to get out of this state is to restart the game.

Is this in the editor or build? I always have hiccups in the editor with the overlay.

@flightCrazed yes this was running in the Editor.

Or you can just get the input from the Legacy Input system that works like every other API on the face of the planet that never has these issues (for a good reason). Unless I'm missing something the OpenXR action system is over-engineering at its finest from what I can tell that OpenVR for some reason thought they should copy.

NOTE: You have to uninstall SteamVR plugin from Unity and restart Editor or it will force Legacy input off.
You only need the OpenVR unity package installed for it to work.

Here is source

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;

#if VRSTUDIOS_XRINPUT_OPENVR
using Valve.VR;
#endif

namespace API.Input
{
	public sealed class XRInput : MonoBehaviour
    {
        public static XRInput singleton { get; private set; }

        public List<InputDevice> devices { get; private set; } = new List<InputDevice>();
        public List<InputDevice> controllers { get; private set; } = new List<InputDevice>();
        public InputDevice handLeft { get; private set; }
        public InputDevice handRight { get; private set; }

        #if VRSTUDIOS_XRINPUT_OPENVR
        private const uint controllerStateLength = OpenVR.k_unMaxTrackedDeviceCount;
        #else
        private const int controllerStateLength = 4;
        #endif
        private XRControllerState[] state_controllers = new XRControllerState[controllerStateLength];
        private uint state_controllerCount;
        private XRControllerState state_controllerLeft, state_controllerRight;

        private void Start()
        {
            // only one can exist in scene at a time
            if (singleton != null)
            {
                Destroy(gameObject);
                return;
		    }
            DontDestroyOnLoad(gameObject);
            singleton = this;

            devices = new List<InputDevice>();
            InputDevices.GetDevicesWithCharacteristics(InputDeviceCharacteristics.Controller, devices);

            InputDevices.deviceConnected += InputDevices_deviceConnected;
		    InputDevices.deviceDisconnected += InputDevices_deviceDisconnected;
		    InputDevices.deviceConfigChanged += InputDevices_deviceConfigChanged;
        }

	    private void OnDestroy()
	    {
            InputDevices.deviceConnected -= InputDevices_deviceConnected;
            InputDevices.deviceDisconnected -= InputDevices_deviceDisconnected;
            InputDevices.deviceConfigChanged -= InputDevices_deviceConfigChanged;
        }

	    private void Update()
        {
            state_controllerCount = 0;
            bool leftSet = false, rightSet = false;

            #if VRSTUDIOS_XRINPUT_OPENVR
            var system = OpenVR.System;
            if (system == null || !system.IsInputAvailable()) return;

            for (uint i = 0; i != controllerStateLength; ++i)
            {
                if (!system.IsTrackedDeviceConnected(i)) continue;

                // update controller state
                if (system.GetTrackedDeviceClass(i) != ETrackedDeviceClass.Controller) continue;
                var state = new VRControllerState_t();
                if (system.GetControllerState(i, ref state, (uint)Marshal.SizeOf<VRControllerState_t>()))
                {
                    var controller = state_controllers[state_controllerCount];
                    controller.connected = true;

                    // update buttons states
                    controller.buttonTrigger.Update((state.ulButtonPressed & 8589934592) != 0);
                    controller.buttonGrip.Update((state.ulButtonPressed & 4) != 0);
                    controller.buttonMenu.Update((state.ulButtonPressed & 2) != 0);
                    controller.button1.Update((state.ulButtonPressed & 4294967296) != 0);

                    // update analog states
                    controller.trigger.Update(state.rAxis1.x);

                    // update joystick states
                    if (state.ulButtonTouched != 0) controller.joystick.Update(new Vector2(state.rAxis0.x, state.rAxis0.y));
                    else controller.joystick.Update(Vector2.zero);

                    // update controller side
                    var role = system.GetControllerRoleForTrackedDeviceIndex(i);
                    switch (role)
                    {
                        case ETrackedControllerRole.LeftHand:
                            controller.side = XRControllerSide.Left;
                            state_controllerLeft = controller;
                            leftSet = true;
                            break;

                        case ETrackedControllerRole.RightHand:
                            controller.side = XRControllerSide.Right;
                            state_controllerRight = controller;
                            rightSet = true;
                            break;

                        default: controller.side = XRControllerSide.Unknown; break;
                    }

                    state_controllers[state_controllerCount] = controller;
                    ++state_controllerCount;
                }
            }
            #else
            foreach (var c in controllers)
            {
                if (!c.isValid || (c.characteristics & InputDeviceCharacteristics.Controller) == 0) continue;

                var controller = state_controllers[state_controllerCount];
                controller.connected = true;

                // update buttons states
                if (c.TryGetFeatureValue(CommonUsages.triggerButton, out bool triggerButton)) controller.buttonTrigger.Update(triggerButton);
                else controller.buttonTrigger.Update(false);

                if (c.TryGetFeatureValue(CommonUsages.gripButton, out bool gripButton)) controller.buttonGrip.Update(gripButton);
                else controller.buttonGrip.Update(false);

                if (c.TryGetFeatureValue(CommonUsages.menuButton, out bool menuButton)) controller.buttonMenu.Update(menuButton);
                else controller.buttonMenu.Update(false);

                if (c.TryGetFeatureValue(CommonUsages.primaryButton, out bool button1)) controller.button1.Update(button1);
                else controller.button1.Update(false);

                if (c.TryGetFeatureValue(CommonUsages.secondaryButton, out bool button2)) controller.button2.Update(button2);
                else controller.button2.Update(false);

                // update analog states
                if (c.TryGetFeatureValue(CommonUsages.trigger, out float triggerValue)) controller.trigger.Update(triggerValue);
                else controller.trigger.Update(0);

                // update joystick states
                if (c.TryGetFeatureValue(CommonUsages.primary2DAxis, out Vector2 joystick)) controller.joystick.Update(joystick);
                else controller.joystick.Update(Vector2.zero);

                // update controller side
                if ((c.characteristics & InputDeviceCharacteristics.Left) != 0)
                {
                    controller.side = XRControllerSide.Left;
                    state_controllerLeft = controller;
                    leftSet = true;
                }
                else if ((c.characteristics & InputDeviceCharacteristics.Right) != 0)
                {
                    controller.side = XRControllerSide.Right;
                    state_controllerRight = controller;
                    rightSet = true;
                }
                else
                {
                    controller.side = XRControllerSide.Unknown;
                }

                state_controllers[state_controllerCount] = controller;
                ++state_controllerCount;
            }
            #endif

            // null memory if no state
            if (!leftSet) state_controllerLeft = new XRControllerState();
            if (!rightSet) state_controllerRight = new XRControllerState();
        }

	    private void InputDevices_deviceConnected(InputDevice device)
	    {
            Debug.Log("XR Device connected: " + device.name);
            devices.Add(device);
            UpdateDevice(device, false);
        }

        private void InputDevices_deviceDisconnected(InputDevice device)
        {
            Debug.Log("XR Device disconnected: " + device.name);
            devices.Remove(device);
            UpdateDevice(device, true);
        }

        private void InputDevices_deviceConfigChanged(InputDevice device)
        {
            Debug.Log("XR Device config changed: " + device.name);
            var index = devices.FindIndex(x => x.name == device.name);
            devices[index] = device;
            UpdateDevice(device, false);
        }

        private void UpdateDevice(InputDevice device, bool removingDevice)
        {
            if (device.characteristics.HasFlag(InputDeviceCharacteristics.Controller))
            {
                if (controllers.Exists(x => x.name == device.name))
                {
				    if (!removingDevice)
				    {
					    var index = controllers.FindIndex(x => x.name == device.name);
					    controllers[index] = device;
				    }
                    else
                    {
                        controllers.Remove(device);
                    }
                }
                else
                {
                    if (!removingDevice) controllers.Add(device);
                }

                if (device.characteristics.HasFlag(InputDeviceCharacteristics.Left))
                {
                    if (!removingDevice) handLeft = device;
                    else handLeft = new InputDevice();
			    }
                else if (device.characteristics.HasFlag(InputDeviceCharacteristics.Right))
                {
                    if (!removingDevice) handRight = device;
                    else handRight = new InputDevice();
			    }
            }
	    }

        public static XRControllerState ControllerState(XRController controller)
        {
            switch (controller)
            {
                case XRController.First: return singleton.state_controllers[0];
                case XRController.Left: return singleton.state_controllerLeft;
                case XRController.Right: return singleton.state_controllerRight;
                case XRController.Merged:
                {
                    var state = new XRControllerState();
                    for (uint i = 0; i != singleton.state_controllerCount; ++i)
                    {
                        var controllerState = singleton.state_controllers[i];
                        if (controllerState.connected) state.connected = true;

                        controllerState.buttonTrigger.Merge(ref state.buttonTrigger);
                        controllerState.buttonGrip.Merge(ref state.buttonGrip);
                        controllerState.buttonMenu.Merge(ref state.buttonMenu);

                        controllerState.button1.Merge(ref state.button1);
                        controllerState.button2.Merge(ref state.button2);
                        controllerState.button3.Merge(ref state.button3);
                        controllerState.button4.Merge(ref state.button4);

                        controllerState.trigger.Merge(ref state.trigger);
                        controllerState.joystick.Merge(ref state.joystick);
					}
                    return state;
                }
            }
            throw new NotImplementedException("XR Controller type not implemented" + controller.ToString());
	    }
    }

    public enum XRController
    {
        /// <summary>
        /// First controller connected
        /// </summary>
        First,

        /// <summary>
        /// All controller states merged
        /// </summary>
        Merged,

        /// <summary>
        /// Left controller states only
        /// </summary>
        Left,

        /// <summary>
        /// Right controller states only
        /// </summary>
        Right
    }

    public enum XRControllerSide
    {
        Unknown,
        Left,
        Right
	}

    public struct XRControllerState
    {
        public bool connected;
        public XRControllerSide side;
        public XRControllerButton buttonTrigger, buttonGrip, buttonMenu;
        public XRControllerButton button1, button2 ,button3, button4;
        public XRControllerAnalog trigger;
        public XRControllerJoystick joystick;
    }

    public struct XRControllerButton
    {
        public bool on, down, up;

        internal void Update(bool on)
        {
            down = false;
            up = false;
            if (this.on != on)
            {
                if (on) down = true;
                else if (!on) up = true;
            }
            this.on = on;
	    }

        internal void Merge(ref XRControllerButton button)
        {
            if (on) button.on = true;
            if (down) button.down = true;
            if (up) button.up = true;
		}
    }

    public struct XRControllerAnalog
    {
        public float value;
        public const float tolerance = 0.1f;

        internal void Update(float value)
        {
            if (value < tolerance) value = 0.0f;
            this.value = value;
	    }

        internal void Merge(ref XRControllerAnalog analog)
        {
            if (value >= tolerance) analog.value = value;
        }
    }

    public struct XRControllerJoystick
    {
        public Vector2 value;
        public const float tolerance = 0.1f;

        internal void Update(Vector2 value)
        {
            if (value.magnitude < tolerance) value = Vector2.zero;
            this.value = value;
        }

        internal void Merge(ref XRControllerJoystick joystick)
        {
            if (value.magnitude >= tolerance) joystick.value = value;
        }
    }
}

Here is how to use API

using UnityEngine;
using API.Input;

public class TestInput : MonoBehaviour
{
    void Update()
    {
        var state = XRInput.ControllerState(XRController.Merged);

        // buttons
        PrintButton(state.buttonTrigger, "ButtonTrigger");
        PrintButton(state.buttonGrip, "ButtonGrid");
        PrintButton(state.buttonMenu, "ButtonMenu");
        PrintButton(state.button1, "Button1");
        PrintButton(state.button2, "Button2");
        PrintButton(state.button3, "Button3");
        PrintButton(state.button4, "Button4");

        // triggers
        PrintAnalog(state.trigger, "Trigger");

        // triggers
        PrintJoystick(state.joystick, "Joystick");
    }

    void PrintButton(XRControllerButton button, string name)
    {
        if (button.down) Debug.Log(name + " down");
        if (button.up) Debug.Log(name + " up");
    }

    void PrintAnalog(XRControllerAnalog analog, string name)
    {
       if (analog.value >= .1f) Debug.Log(name + " " + analog.value.ToString());
	}

    void PrintJoystick(XRControllerJoystick joystick, string name)
    {
        if (joystick.value.magnitude >= .1f) Debug.Log($"{name} {joystick.value.x}x{joystick.value.y}");
    }
}

Issue for me is I can't go back to legacy due to the fact that the legacy plugin overrides the camera far plane somehow and I need it to stay at 250k as I am making a flight sim. If anyone knows how to turn that 'feature' off I would.

Issue for me is I can't go back to legacy due to the fact that the legacy plugin overrides the camera far plane somehow and I need it to stay at 250k as I am making a flight sim. If anyone knows how to turn that 'feature' off I would.

I'm using the Legacy OpenVR plugin and Unity XR Input in 2019.4 with a large far plane without issue.

How large exactly? When I upgraded the plugin the issue went away. It was rendering the skybox at about 50k for some reason.

@hollowworldgames Look at my example. You don't need the SteamVR plugin to be installed ONLY the OpenVR package from Unity package manager. This is the cleanest way to do it IMO... even if you use the new Input API.

This is a massive pain in the ass, wasn't input working in an earlier version too?

This is a massive pain in the ass, wasn't input working in an earlier version too?

Yes input was working in an early version and they took it away from under us.

g33rt commented

I've had it. I'm dropping SteamVR/Vive support. I'm now recommending customers to buy Oculus or WMR headsets. Bye

I've had it. I'm dropping SteamVR/Vive support. I'm now recommending customers to buy Oculus or WMR headsets. Bye

That's pretty dramatic when multiple ways of easily supporting SteamVR have been shown in this thread.

I've had it. I'm dropping SteamVR/Vive support. I'm now recommending customers to buy Oculus or WMR headsets. Bye

That's pretty dramatic when multiple ways of easily supporting SteamVR have been shown in this thread.

Idk, I think the two points he brought up came the minds of many developers. Despite the effort that myself and others in this thread have made, it was still in my game's best interest to 1)Drop future SteamVR/Vive controller support and 2)Recommend using an Oculus.

Aside from this development issue, the Vive Cosmos headsets have had lacked controller support in games such as Skyrim VR (Where a workaround is needed) for years. We will probably go the same route, requiring Vive users to use custom bindings.

Additionally, most of our players are using Oculus headsets anyways. So while we will offer to keep existing content compatible for that population, new features are being developed using the XR Interaction system and I hope that OpenVR is fully supported in the future. I'm not abandoning Vive, just not prioritizing developing for it.

Or you can just get the input from the Legacy Input system that works like every other API on the face of the planet that never has these issues (for a good reason). Unless I'm missing something the OpenXR action system is over-engineering at its finest from what I can tell that OpenVR for some reason thought they should copy.

How do you reference this in another script? Using Valve Index, I am referencing XRInput in another script and trying to pull controller values into bools as a test. None of these return true despite me having the right controller on and pressing the trigger etc.

rightTriggerPressed = XRInput.ControllerState(XRController.Right).buttonTrigger.down; test = XRInput.ControllerState(XRController.Right).buttonGrip.down; test1 = XRInput.ControllerState(XRController.Right).connected;

only works with legacy vr and 2019.4. It doesn't work with the xrmanagement and steamvr store asset. I would use it but I have an issue with the skydome being rendered to close with legacy vr and understand the buttons on the knuckles are not all there or correct in legacy as well.

only works with legacy vr and 2019.4

It should work with anything as long as you remove SteamVR plugin from Unity and restart Editor. OpenVR only allows one Input system at a time for no good reason.
Look at updated comment.
I'll probably make a Git repo for this and add support for new Input system and abstract away OpenVR's abstractions and maximize compatibility.

legacy vr was removed in 2020.1

This has nothing to do with Unity. I'm using OpenVR directly. It doesn't matter what Unity does for the most part.
Unless OpenVR removes legacy API (which hasn't happened) & Unity updates/links to that versions .lib it will work.

I managed somewhat to make thing work in Unity 2019.4 LTS and SteamVR Plugin 2.6.0b4 . I modified the code of the interaction toolkit so that the XR Controller takes the input from the InputDevice on all platforms with the exception of SteamVR where it takes the input from SteamVR_Action. I can't share the code here because I'm using it for a commercial project, but if someone wants some more details, I'm open to share them.

I mean, I made a hack that works for usual cases (interactor/interactables and detection of grip/trigger/etc) not in all cases, it is still a hack and it is quite dirty... but it makes me go forward with my job. I tested builds for PC (OpenVR) and also for Quest (Oculus-Android), input works in all cases, but you must build for x64 on PC.

I managed somewhat to make thing work in Unity 2019.4 LTS and SteamVR Plugin 2.6.0b4 . I modified the code of the interaction toolkit so that the XR Controller takes the input from the InputDevice on all platforms with the exception of SteamVR where it takes the input from SteamVR_Action. I can't share the code here because I'm using it for a commercial project, but if someone wants some more details, I'm open to share them.

I mean, I made a hack that works for usual cases (interactor/interactables and detection of grip/trigger/etc) not in all cases, it is still a hack and it is quite dirty... but it makes me go forward with my job. I tested builds for PC (OpenVR) and also for Quest (Oculus-Android), input works in all cases, but you must build for x64 on PC.

Any tips for modifying the XR Interaction toolkit to take other inputs?

I hacked the XR Interaction toolkit to take SteamVR inputs by adding a SetInputOverride function to InputHelpers.cs. Here's my modified file. https://pastebin.com/6WD9eN6D

So anything that uses InputHelpers in the toolkit should work. You just grab controller inputs from the SteamVR plugin and pass them to InputHelpers through that added function. When InputHelpers fails to get the input from XR it will fall back to those values you provide from SteamVR.

I hacked the XR Interaction toolkit to take SteamVR inputs by adding a SetInputOverride function to InputHelpers.cs. Here's my modified file. https://pastebin.com/6WD9eN6D

pass them to InputHelpers through that added function.

I'm using a different implementation for input, when calling public static void SetInputOverride(this InputDevice device, string inputName, object value), what do I pass for 'object value' and is there any dictionary for the 'value', 'inputDevice', 'inputName' entries so I can be sure I am passing it the right things?

For inputDevice, I am passing the UnityEngine.XR.InputDevice, but inputName and value are a bit vague to me!

Thanks for the help

I'm using a different implementation for input, when calling public static void SetInputOverride(this InputDevice device, string inputName, object value), what do I pass for 'object value' and is there any dictionary for the 'value', 'inputDevice', 'inputName' entries so I can be sure I am passing it the right things?

For inputDevice, I am passing the UnityEngine.XR.InputDevice, but inputName and value are a bit vague to me!

Look at the s_ButtonData array for the input name strings it's looking for. The value is simply the actual current value of the input. It can be either a bool, a float or a Vector2, which is why it's of type object so it can take all 3.

Hello all, in the end, I stripped away only the code of the hack and made this guide on how I solved it. I hope it can be useful for your applications as well. I wanted to make the XR Interaction Toolkit + Unity XR Plug-In Management work with SteamVR, so that I could make a program crossplatform between Vive, Rift and Quest.

You can find the guide on my blog: https://skarredghost.com/2020/09/25/steamvr-unity-xr-interaction-toolkit-input/
I hope it can be useful to someone of you!

@TonyViT

First of all thank you for this wonderful article. I struggled with that SteamVR Implementation and now its working. I have done every step of your guide, Normal Object Grab is working fine + with Pointer Grab and UI Elements interaction. But something is not working correctly. Im using the HTC VIVE Pro Eye. (Quest is working perfectly with your "Hack") For Example:

private void Start()
{
    rightController = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
}

public bool CheckIfActivated(XRController controller)
{
    controller.inputDevice.TryGetFeatureValue(CommonUsages.grip, out pressTreshold); 
    Debug.Log("Grip: "+ pressTreshold);
    controller.inputDevice.TryGetFeatureValue(CommonUsages.trigger, out pressTreshold); 
    Debug.Log("Trigger: " +pressTreshold);
    
    if (pressTreshold> activationThreshold)
        return true;
    else
        return false;
}
  • Both CommonUsages.trigger & CommonUsages.grip only reacts to Trigger Button.
  • CommonUsages.grip -> Values from 0 to 1 (float) reacts to Trigger Button from Controller
  • CommonUsages.trigger -> Value 0 or 1 (int - looks likes Pressed or Not) reacts to Trigger Button from Controller.
  • CommonUsages.triggerButton reacts to Trigger Button -> works
  • CommonUsages.gripButton reacts to Grip Button -> works
  • CommonUsages.primaryAxis2D -> Only hard steps from 0 to 1 or -1 are displayed.

Could help me what im doing wrong? Is it also possible to get the MenuButton + SecondaryButton(Below Touchpad) to work? Big Thanks in Advance!!!

Hey @Schumsta glad that the hack worked out for you... at least in part. :)

Most probably to make things work completely, you have to modify the code of my hack.

First of all, with the hack, don't use anymore InputDevices.GetDeviceAtXRNode(XRNode.RightHand), but take directly the reference to the XRController and then access the InputDeviceWrapper through it. the problem is that it is exactly the inputDevice class that can't access SteamVR, so you should go through my hack and use the InputDeviceWrapper through the XRController.inputDevice to make things work also on SteamVR.

Then, you see all those problems because I implemented a naive hack, with the basic features. The basic features are the ones provided out of the box from the standard SteamVR Input System. At a certain point in the hack, I made you do "save and generate" on the input system, without changing anything. But those default settings have just a dull trigger that has only on/off states for instance, and so is for the thumbstick.
What you should do is:

  • Make a research on how to implement the features that you want as Actions in the SteamVR Input System 2.0 (this post https://medium.com/@sarthakghosh/a-complete-guide-to-the-steamvr-2-0-input-system-in-unity-380e3b1b3311 can be of help). E.g. you can implement an action for the thumbstick with smooth values called Thumbstick
  • Then implement these things in the InputDeviceWrapper file. So if you implement an Action called Thumbstick that returns a Vector2 for the position of the touchpad, you can modify the Vector2 part of the InputDeviceWrapper (line 205) like this:
public bool TryGetFeatureValue(InputFeatureUsage<Vector2> usage, out Vector2 value)
{
#if UNITY_STANDALONE
	if (m_isSteamVR && m_deviceNode.IsHands())
	{
		if (usage == CommonUsages.primary2DAxis)
		{
			value = SteamVR_Actions._default.Thumbstick[m_deviceNode.ToSteamVrSource()].axis2D;

			return true;
		}              
	}
#endif
	return m_inputDevice.TryGetFeatureValue(usage, out value);
}

This way, you don't only get discrete values from it, but you get the continuous values from the action that you have created.

I hope it is clear, otherwise tell me.

Thanks for your fast response. I got it to work with the Touchpad-Input as Vector2. But i dont know what im doing wrong with the SystemButton (below TouchPad). Normal Click-Event (SteamVR Input) -> Bool.

So i use

        public bool TryGetFeatureValue(InputFeatureUsage<bool> usage, out bool value)
        {
#if UNITY_STANDALONE
            if (m_isSteamVR && m_deviceNode.IsHands())
            {
                if (usage == CommonUsages.triggerButton)
                {
                    value = SteamVR_Actions._default.GrabPinch[m_deviceNode.ToSteamVrSource()].state;

                    return true;
                }
                else if (usage == CommonUsages.gripButton)
                {
                    value = SteamVR_Actions._default.GrabGrip[m_deviceNode.ToSteamVrSource()].state;

                    return true;
                } else if(usage == CommonUsages.menuButton)  //SYSTEM BUTTON - BELOW TOUCHPAD- NOT WORKING
                {
                    value = SteamVR_Actions._default.MenuButton[m_deviceNode.ToSteamVrSource()].state;
                    return true;
                }
                else if (usage == CommonUsages.primaryButton) //PRIMARY BUTTON - ABOVE TOUCHPAD- WORKING
                {
                    value = SteamVR_Actions._default.PrimaryButton[m_deviceNode.ToSteamVrSource()].state;
                    return true;
                }
            }
#endif
            return m_inputDevice.TryGetFeatureValue(usage, out value);
        }

But i dont get any Values from the SystemButton.... The button is false the whole time. Big Thanks Again in Advance!

Hello all, in the end, I stripped away only the code of the hack and made this guide on how I solved it. I hope it can be useful for your applications as well. I wanted to make the XR Interaction Toolkit + Unity XR Plug-In Management work with SteamVR, so that I could make a program crossplatform between Vive, Rift and Quest.

You can find the guide on my blog: https://skarredghost.com/2020/09/25/steamvr-unity-xr-interaction-toolkit-input/
I hope it can be useful to someone of you!

Tony!!!! You're awesome man. Thank you verry much. It works great for me and the test project I'm doing. I'm really glad I anticipated potential issues doing a pre prod test project as this is a REALLY big issue.

Hello,
Any news on that issue? I'm developping crossplatform VR games and I don't want to use the SteamVR input plugin. The previous versions of the plugin was OK with the new input system, why have you removed its support?
I understand OpenXR is great but it's not in Unity yet.

@zite so you closed #9 (comment) because it is a duplicate of that issue here. But why on earth is this issue here closed then?

A single input system is definitely the goal. We'll either support or work on a plugin that enables vr developers to target one cross platform api. But, it won't be in this plugin.

@zite Hi, is this still the case? If so any word on when this might be available? Thanks!

There has been finally some official communications regarding OpenXR support in Unity:
https://forum.unity.com/threads/unitys-plans-for-openxr.993225/
TL;DR: "We plan to have early previews of Unity’s support of OpenXR on some of these platforms as early as the end of this year (Unity 2020 release cycle)."

There has been finally some official communications regarding OpenXR support in Unity:
https://forum.unity.com/threads/unitys-plans-for-openxr.993225/
TL;DR: "We plan to have early previews of Unity’s support of OpenXR on some of these platforms as early as the end of this year (Unity 2020 release cycle)."

About time!!
Thanks for sharing!

I'm probably late to the party, and just echoing what others have said but if the aim is all about cross platform support, then please just support the Unity XR input APIs (https://docs.unity3d.com/Manual/xr_input.html). This is what cross platform support looks like. Right now I have to grab another 3rd party plugin (not even served by the package manager, bloating the repository), and pipe that input into another layer so that my app has a common API. The whole purpose of the Unity XR plugins ecosystem was to avoid doing exactlty that. The common api should be at unity engine level, not at open vr plugin level.

Just chiming in that support for the new Input System would be greatβ€”since I think previous versions of this plugin did support it, having it enabled for a stable release would be awesome, since newer plugins could be pretty far off.

The other solution seems to be writing a wrapper for SteamVR's input, which doesn't sound super appealing.

It's 2021 and I still need this system before I switch to Unity 2020. Do you guys need any help on implementation?

It's 2021 and I still need this system before I switch to Unity 2020. Do you guys need any help on implementation?

Use Unity OpenXR (not OpenVR) plugin

This is just ridiculous, both you and unity are just too proud to do a quick solution, it was working before, it's just detecting the click of simple buttons. You could add a custom unity input device wrapper that reads from your old input, this is taking more than a year already, and where's your beautiful open xr solution? Anyway, I know you won't even read this comment. I hope you solve it this year

This is just ridiculous, both you and unity are just too proud to do a quick solution, it was working before, it's just detecting the click of simple buttons. You could add a custom unity input device wrapper that reads from your old input, this is taking more than a year already, and where's your beautiful open xr solution? Anyway, I know you won't even read this comment. I hope you solve it this year

Use Unity OpenXR (not OpenVR) plugin

spvn commented

This is just ridiculous, both you and unity are just too proud to do a quick solution, it was working before, it's just detecting the click of simple buttons. You could add a custom unity input device wrapper that reads from your old input, this is taking more than a year already, and where's your beautiful open xr solution? Anyway, I know you won't even read this comment. I hope you solve it this year

Use Unity OpenXR (not OpenVR) plugin

Are you referring to this? https://docs.unity3d.com/Packages/com.unity.xr.openxr@0.1/manual/index.html

In the documentation it says that it supports WMR and Hololens 2 only...

This is just ridiculous, both you and unity are just too proud to do a quick solution, it was working before, it's just detecting the click of simple buttons. You could add a custom unity input device wrapper that reads from your old input, this is taking more than a year already, and where's your beautiful open xr solution? Anyway, I know you won't even read this comment. I hope you solve it this year

Use Unity OpenXR (not OpenVR) plugin

Seems like it's in early beta yet, but it's something. I tried and the controller models have offset when compared to the old system

This is just ridiculous, both you and unity are just too proud to do a quick solution, it was working before, it's just detecting the click of simple buttons. You could add a custom unity input device wrapper that reads from your old input, this is taking more than a year already, and where's your beautiful open xr solution? Anyway, I know you won't even read this comment. I hope you solve it this year

Use Unity OpenXR (not OpenVR) plugin

Are you referring to this? https://docs.unity3d.com/Packages/com.unity.xr.openxr@0.1/manual/index.html

In the documentation it says that it supports WMR and Hololens 2 only...

This has more info about the current state: https://forum.unity.com/threads/unity-support-for-openxr-in-preview.1023613/

It does support both SteamVR and Oculus as OpenXR runtimes, but is in preview and still has a bit to go.

Here is an agnostic solution for others running into this: https://github.com/VRStudios/Unity3D-XRInput

spvn commented

Here is an agnostic solution for others running into this: https://github.com/VRStudios/Unity3D-XRInput

To clarify, is this to be used together with this repo (Valve's OpenXR plugin) and also Oculus' OpenXR plugin at the same time?

To clarify, is this to be used together with this repo (Valve's OpenXR plugin) and also Oculus' OpenXR plugin at the same time?

Yes its to be used with this repo. Because Valve doesn't support Unity3D's generic/agnostic input system like Oculus does, it exposes OpenVR's existing Input system (thats modeled correctly & been around since day one) or Unity3D's Input system through its own generic/agnostic layer.

In short enable SteamVR/OpenVR input when publishing to Steam store or disable it & it falls back to Unity's input system that supports Oculus, etc

spvn commented

To clarify, is this to be used together with this repo (Valve's OpenXR plugin) and also Oculus' OpenXR plugin at the same time?

Yes its to be used with this repo. Because Valve doesn't support Unity3D's generic/agnostic input system like Oculus does, it exposes OpenVR's existing Input system (thats modeled correctly & been around since day one) or Unity3D's Input system through its own generic/agnostic layer.

In short enable SteamVR/OpenVR input when publishing to Steam store or disable it & it falls back to Unity's input system that supports Oculus, etc

I see, so that means I have to manually enable/disable it based on the platform (Oculus or Vive) I'm running it on, correct? the same build won't work on both platforms automatically until Valve gets around to fixing inputs in this plugin and we no longer need to use your repo. Is my understanding of the situation right?

thanks loads for sharing your solution btw, I'm desperately trying to figure out what I'm supposed to use right now to support both Oculus and Vive since none of the OpenXR stuff seems to be ready.

I see, so that means I have to manually enable/disable it based on the platform (Oculus or Vive) I'm running it on, correct? the same build won't work on both platforms automatically

Yes thats correct. While I could update & add support for this & auto detect what platform Unity has init, its actually a bad idea in general. If you have for Example Oculus store/services running but try to play a game using Oculus with SteamVR... Unity3D gets very confused & triggers something in OpenVR inputs layer to stop working. This situation is actually rather common so its best make builds & publish for a specific platform. Compile once run-everywhere is a failed concept in general for a lot of situations IMO.

zite commented

If you're looking for cross platform support I would take a look at unity's openxr plugin. That supports both oculus and steamvr in one plugin. It is still in development, but there's a preview linked above: https://forum.unity.com/threads/unity-support-for-openxr-in-preview.1023613/

Also I will add OpenXR support to the agnostic Input layer later which avoids needing to change game code yet again to a new Input system. Native OpenXR input solutions are going to be far more verbose anyway.

zite commented

The point of OpenXR is to be a singular platform agnostic layer. Otherwise people like you (and me at a previous company) have to continuously update their abstraction layer whenever any of the supported plugins have a change. If you happen to stop updating it for some reason, it may stop working (like mine did). All the major vr companies are moving towards OpenXR to solve these problems.

Also, utilizing legacy input as you suggest, finger tracking data will not be available to you as those functions require SteamVR Input.

But of course, you're welcome to make your own thing if our options aren't working for you.

spvn commented

If you're looking for cross platform support I would take a look at unity's openxr plugin. That supports both oculus and steamvr in one plugin. It is still in development, but there's a preview linked above: https://forum.unity.com/threads/unity-support-for-openxr-in-preview.1023613/

Naturally this would be the ideal plugin to use. But it's been released for a month and is still in preview only (Vive and Oculus aren't even considered officially supported devices, you can't deploy to the Quest, and users are reporting all sorts of bugs on the forums still), so it's barely useable. Unfortunately I need to start a project right now and don't have the luxury of waiting for OpenXR to mature.

zite commented

If you're looking for cross platform support I would take a look at unity's openxr plugin. That supports both oculus and steamvr in one plugin. It is still in development, but there's a preview linked above: https://forum.unity.com/threads/unity-support-for-openxr-in-preview.1023613/

Naturally this would be the ideal plugin to use. But it's been released for a month and is still in preview only (Vive and Oculus aren't even considered officially supported devices, you can't deploy to the Quest, and users are reporting all sorts of bugs on the forums still), so it's barely useable. Unfortunately I need to start a project right now and don't have the luxury of waiting for OpenXR to mature.

Ah, that is unfortunate. Hopefully those issues will be resolved soon.

spvn commented

If you're looking for cross platform support I would take a look at unity's openxr plugin. That supports both oculus and steamvr in one plugin. It is still in development, but there's a preview linked above: https://forum.unity.com/threads/unity-support-for-openxr-in-preview.1023613/

Naturally this would be the ideal plugin to use. But it's been released for a month and is still in preview only (Vive and Oculus aren't even considered officially supported devices, you can't deploy to the Quest, and users are reporting all sorts of bugs on the forums still), so it's barely useable. Unfortunately I need to start a project right now and don't have the luxury of waiting for OpenXR to mature.

Ah, that is unfortunate. Hopefully those issues will be resolved soon.

Are there still plans to support controller inputs with this Unity XR Plugin from Valve? Or are we just going to have to wait for Unity's OpenXR Plugin to mature?

The point of OpenXR is to be a singular platform agnostic layer.

This is the argument people made for OpenGL or Vulkan. Its simply doesn't hold true. Of course it depends on your targets.

Not everyone uses OpenXR like Pico for example & if you're on Unity LTS OpenXR isn't a solution either. Also OpenXR is not structured in a simple way from what I've seen (unless mistaken its over engineered to solve problems people don't have such as rigging structures etc better suited as frameworks). Input APIs have been done correctly since the 80s (button bit-fields & axis values with extra meta-data if needed and thus IDK what ppl are thinking with this new stuff to be frank).

Also I made this specifically because people at work were complaining so much about how bad the input options are. So figured I'd just share what helped them.

zite commented

The point of OpenXR is to be a singular platform agnostic layer.

Not everyone uses OpenXR like Pico for example & if you're on Unity LTS OpenXR isn't a solution either. Also OpenXR is not structured in a simple way from what I've seen (unless mistaken its over engineered to solve problems people don't have such as rigging structures etc better suited as frameworks). Input APIs have been done correctly since the 80s (button bit-fields & axis values with extra meta-data if needed).

I made this specifically because people at work were complaining so much about how bad the input options are.

I'm not sure how far along they are, but it looks like Pico is at least working on OpenXR support: https://sdk.picovr.com/docs/OpenXRMobileSDK/en/index.html

There is certainly UX work to be done around making OpenXR Input easy to use, but we believe it solves a lot of issues that developers have had. Namely: new controllers with different layouts coming out, development time reduction for developing against a singular api, and input actions that allow for users to control how they interact with your game (accessibility, preference, half broken controller, etc). That said, it is quite different than what we've been doing for decades, and changing something like that takes a bit of iteration. Hopefully you'll take a look again once Unity's implementation has matured.

spvn commented

Does that mean we shouldn't expect any updates to this particular repo to support inputs in the near future (next 6 months)? Should I just stick to looking out for Unity's implementation to mature?