ValveSoftware / unity-xr-plugin

OpenVR plugin for Unity's XR API
BSD 3-Clause "New" or "Revised" License
309 stars 64 forks source link

Unity XR Input / Unity Input System not working #16

Closed hollowworldgames closed 4 years ago

hollowworldgames commented 4 years ago

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 4 years ago

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

kendrome commented 4 years ago

@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 4 years ago

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.

MrMabulous commented 4 years ago

@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.

stonebits commented 4 years ago

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 4 years ago

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

stonebits commented 4 years ago

Cool, Thanks!

zite commented 4 years ago

@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).

MrMabulous commented 4 years ago

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

kendrome commented 4 years ago

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.

MrMabulous commented 4 years ago

@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?

wizgrav commented 4 years ago

@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

MrMabulous commented 4 years ago

@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)

wizgrav commented 4 years ago

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

flightCrazed commented 4 years ago

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

kendrome commented 4 years ago

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.

halfpasttense commented 4 years ago

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.

wizgrav commented 4 years ago

@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

halfpasttense commented 4 years ago

@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.

wizgrav commented 4 years ago

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

kendrome commented 4 years ago

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.

wizgrav commented 4 years ago

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

halfpasttense commented 4 years ago

@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.

kendrome commented 4 years ago

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.

halfpasttense commented 4 years ago

@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.

flightCrazed commented 4 years ago

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?

kendrome commented 4 years ago

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.

flightCrazed commented 4 years ago

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!

hollowworldgames commented 4 years ago

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.

wizgrav commented 4 years ago

@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

ary1111 commented 4 years ago

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.

flightCrazed commented 4 years ago

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.

flightCrazed commented 4 years ago

@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!

flightCrazed commented 4 years ago

@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.

ary1111 commented 4 years ago

@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.

wizgrav commented 4 years ago

@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

flightCrazed commented 4 years ago

@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

flightCrazed commented 4 years ago

@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

hollowworldgames commented 4 years ago

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

ary1111 commented 4 years ago

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;
}
flightCrazed commented 4 years ago

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

zite commented 4 years ago

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

halfpasttense commented 4 years ago

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.

halfpasttense commented 4 years ago

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.

halfpasttense commented 4 years ago

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

flightCrazed commented 4 years ago

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.

halfpasttense commented 4 years ago

@flightCrazed yes this was running in the Editor.

zezba9000 commented 4 years ago

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

```cs 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 devices { get; private set; } = new List(); public List controllers { get; private set; } = new List(); 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(); 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())) { 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 { /// /// First controller connected /// First, /// /// All controller states merged /// Merged, /// /// Left controller states only /// Left, /// /// Right controller states only /// 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}");
    }
}
hollowworldgames commented 4 years ago

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.

kendrome commented 4 years ago

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.