Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question OpenXR and OpenVR together?

Discussion in 'XR Interaction Toolkit and Input' started by myaydin, May 21, 2021.

  1. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,450
    Has anyone actually reported the Controller positions issue mentioned above? If so can you please post the case number here so I can chase?
     
  2. ms82119

    ms82119

    Joined:
    Dec 26, 2016
    Posts:
    3
    I’ve read through this whole thread a couple of times to make sure I understand what people are experiencing and trying to find a solution to my own problem.

    From what I can see there are a couple of related but different issues being discussed here, i.e. getting Vive trackers to work with a Steam VR headset, getting them to work with non Lighthouse headsets, and some other variations where controllers and/or headsets are not present too, but all using OpenXR.

    My particular problem is with the first case and simplest case, a Vive Pro headset, and a Vive Tracker 1.0 using OpenXR in Unity. When I use the TrackerProfile that was posted earlier in this thread, and add it as a Input Profile in the OpenXR settings and then run my Scene, I can see all the various types of trackers (e.g. chest, left foot, etc) listed in the Input Debugger, but none of them are registering any movement when I move the tracker. Even when I tag the tracker with the appropriate body part in the SteamVR setup.

    I see others have had this same problem, but I also saw some indications that they may have got it working, then hit other problems. So I just want to ask here for clarity sake has anyone been able to get a Lighthouse headset with a Vive Tracker up and running together in Unity, and if so can you say how your setup is different from mine?

    I have the latest LTS version 2021.1.17, latest SteamVR Beta 1.21.12, I’m using the Vive tracker profile that was in post #21 of this thread by @thep3000. That post also seems to show the tracker working… If that test package was available to download I could try that.
     
  3. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,450
    @ms82119 You need to use some trial and error here so first off check you never enabled multipledrivers: true in steamvr config or just clean install SteamVR latest for good measure.

    Then try my repro project here
    https://forum.unity.com/threads/openxr-and-openvr-together.1113136/#post-7913977

    Just make sure the Vive tracker profile is enabled, check in SteamVR settings that it is set as the default OpenXR runtime.

    Once its working you will see it is currently unusable as the trackers work but the left and right controllers are stuck tracking in the same position which is one of the outstanding issues I hope someone has reported, if not I will report it to Unity also. I'll post back my case number if I do!

    If you are still stuck refer to my other posts further back in this thread for other tips.
     
  4. ms82119

    ms82119

    Joined:
    Dec 26, 2016
    Posts:
    3
    Hey @ROBYER1, thanks for the reply. I have good news/ bad news to report! The good part is that I was indeed able to get my tracker to be recognized and tracked using your demo project. The bad news is that I also could see the problem you outlined with the two controllers being represented at the same coordinates but didn’t find an immediate solution to that one.

    For those that might face similar challenge to me in determining if tracking is working using robyer1’s demo project, there are a couple of things to look out for. 1) In this particular demo the action tracking for the tracker was based off the left elbow (I had set up my Vive tracker as left foot). 2) If you look at the output from the Input Debugger to tell you if tracking is working while the scene is playing, make sure you put your thumb over the light sensor inside the headset so it thinks you’re wearing it. I realized that unity doesn’t show any movement output in the Input Debugger window when it thinks the headset is not in use. Once I got those two things straight i could see that the tracker was indeed being tracked. This should hopefully allow me to get it working in my own project now, I hope!

    As I said earlier I didn’t find a solution to the controllers being at the same coordinates and I didn’t have enough time to get really deep into it. I think i noticed this problem even when I didn’t have the tracker running, so it may be independent of that. I also could see that the buttons on the separate controllers all map correctly, and in fact if you look at the Input Debugger for the left and right controllers you can see the position and angles track independently (which you want). It makes me think that the issue more on the unity side the way the scene is setup, although the action rules all seemed to be referring to the left and right controller correctly as you would expect. So sorry I’m not able to add much more insight at the moment. When I get some more time I will look at this further and see if it is also a problem in my project.
     
  5. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,450
    @thep3000 @LucaSerafino @JoRouss @gems2020 @ms82119 Just letting you all know that I have now reported the controllers stuck together when using HTC Vive Tracker Controller Profile at this Unity bug:

    (Case 1415203) [OpenXR][SteamVR] Using Vive trackers causes the XR Controllers to be stuck together and not tracked separately

    Please let me know if it is already a duplicate if you reported the issue before me and I can inform Unity QA

    Any time I contacted Unity QA before they did not have access to HTC Vive Trackers for months so if anyone in Unity XR team could look into this big issue it would be appreciated thanks otherwise this could take a long time to validate despite many others here mentioning. @mfuad @Matt_D_work are any of you still involved in the XR team? This is a blocker for using major new OpenXR/SteamVR features which are already available.
     
  6. thep3000

    thep3000

    Unity Technologies

    Joined:
    Aug 9, 2013
    Posts:
    400
    Regarding the two controllers both tracking as the left controller:

    There is a bug in the sample where the right hand bindings in the sample are showing up as left hand because of the mechanism in which they were implemented (if using input system > 1.0.2). You can manually change these to right hand and the left and right will track independently (and vive trackers work as well).

    The sample is fixed in the 1.4.0 package release which is coming out soon. But it's just an issue with the sample, so changing it in your local scenes should be good for the future.
     

    Attached Files:

    ROBYER1 likes this.
  7. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,450

    Hi @thep3000, I saw my case 1415203 was closed for this, but I already have another repro project that was never using the samples, a project that seemed to always work fine without the HTC Vive Tracker profile included.

    I have been told by my testers that they experience the right controller stuck to the left controller in this project
    I have of course double checked my action based controllers are set up correctly as left and right hands and it all works fine for me at least without the HTC Vive Tracker profile added.

    I'm just waiting to re-verify this with the tester this evening then if the issue still exists in this project, I will update the case with the new repro project using Action based XR Controllers.

    I don't have 2 vive wands here just one but I tested my scene with the Oculus Quest and it seemed to be fine but I can't use the Vive trackers with the quest so that may be the issue when using HTC Vive or Index controllers for my testers.

    upload_2022-4-4_21-37-58.png

    upload_2022-4-4_21-35-2.png
     
  8. thep3000

    thep3000

    Unity Technologies

    Joined:
    Aug 9, 2013
    Posts:
    400
    If you get me a project that repros the issue, I'll take a look. I just got the ability to pair 2 controllers and a vive tracker today so I'm now equipped to look into this sort of issue.
     
  9. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,450
    I will PM you a private link to it, I just ordered another Vive wand which should arrive this week too. If you request access on the link I can allow you to download it. Instructions in the PM also, thanks for your help.
     
    thep3000 likes this.
  10. thep3000

    thep3000

    Unity Technologies

    Joined:
    Aug 9, 2013
    Posts:
    400
    If anyone else is observing single controller tracking and their bindings are set up properly - make sure you're using SteamVR beta - seems that the stable release right now exhibits the single controller tracking issue but the beta is working fine.
     
  11. UCRyan

    UCRyan

    Joined:
    May 11, 2020
    Posts:
    4
    Hello All,

    It's possible this is resolved, but I searched all morning to no avail, so I wanted to post my workaround here for anyone who is still having issues getting Vive Trackers and Wands to work at the same time.

    The attached script is a mash up of the script uploaded by @thep3000 and the default HTCViveControllerProfile in the OpenXR package. Remove the original vive controller profile and viv tracker profile and use only "HTC Vive Controller Mod." The same profile supports controllers and trackers.

    The workaround is creating the left and right controllers as unique layouts/action maps. This isn't pretty, but so far it is working for me in 2020.3.24 (I have only testing with 2 controllers and 1 tracker so far).

    Hope it helps!
     

    Attached Files:

  12. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,450
    @UCRyan Thanks for the script but you don't need to do that, just update and use SteamVR beta latest version as of this post and both will wands and trackers work together. I cross verified this today.

    The only outstanding issues now on Valve's end are:

    1. SteamVR Null driver and Vive trackers causes a black screen with OpenXR
    2. SteamVR multipledrivers = true being set causes a black screen when using Vive trackers and another driver headset like an Oculus or WMR headset combined with a base station playspace (used to work fine in OpenVR for vive trackers + Oculus.Quest for things like VR Chat etc)
     
    JakeFulcro likes this.
  13. UCRyan

    UCRyan

    Joined:
    May 11, 2020
    Posts:
    4
    @ROBYER1 much appreciated :D Unfortunately, I can't rely on SteamVR beta. I'm not comfortable asking end-users to to switch to beta, and the app also needs to work in Oculus via OpenXR. Which, as a side note, presents the same single controller issue when using Oculus runtime as the OpenXR host (obviously sans trackers) when the Vive profiles are present. It would be possible to work around that with a separate Oculus-Only distribution, but that sort of defeats the purpose of OpenXR and having a single platform :)

    (Edited because, on reflection, I can't actually confirm that Oculus users are using Oculuis runtime, it's possible they have SteamVR set as the OpenXR host. But at any rate, that uncertainty about which host they are using and what SteamVR version they have means I needed a workaround independent of the current beta)
     
    ROBYER1 likes this.
  14. MaciejZareba_4experience

    MaciejZareba_4experience

    Joined:
    Mar 11, 2020
    Posts:
    21
    Hi, I've been stuck on same place as JoRouss and Robyer1. (Unity 2019.2.19), Steam VR Beta 1.21.12

    After adding HTCViveTrackerProfile
    upload_2022-4-26_16-13-11.png

    1) My both index controllers are stuck in same place as LeftController.

    upload_2022-4-26_16-16-21.png

    2) My Input debugger is seeing HTCViveTrackerOpenXR devices (I used left foot rotation and position for my test object)
    upload_2022-4-26_16-24-27.png

    3) When i Enable game object with TrackedPoseDriver (InputSystem) for my test object I'm getting those errors
    upload_2022-4-26_16-26-31.png

    (2nd error description)
    InvalidOperationException while executing 'performed' callbacks of 'AdditionalTracker - TPD - Position[/HTCViveTrackerOpenXR/devicepose]'
    UnityEngine.InputSystem.LowLevel.NativeInputRuntime/<>c__DisplayClass10_0:<set_onBeforeUpdate>b__0 (UnityEngineInternal.Input.NativeInputUpdateType)
    UnityEngineInternal.Input.NativeInputSystem:NotifyBeforeUpdate (UnityEngineInternal.Input.NativeInputUpdateType)
     
    Last edited: Apr 27, 2022
  15. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,450
    Just switch to SteamVR beta please and post back here if you still have an issue. As others here mentioned, SteamVR beta fixes that issue.
     
  16. MaciejZareba_4experience

    MaciejZareba_4experience

    Joined:
    Mar 11, 2020
    Posts:
    21
    I'm using Steam VR beta
     
  17. MaciejZareba_4experience

    MaciejZareba_4experience

    Joined:
    Mar 11, 2020
    Posts:
    21
    Hi

    I've managed to make it partially work. In my case i had to reset all devices, SteamVR and re assign vive trackers to SteamVR. All vive trackers data is working just fine.Unfortunately when I'm adding HTC Vive Tracker Profile (posted in this thread) to OpenXR settings my Left and Right index controllers are getting position and rotation from left controller. All other input data (float Trigger, float Grip, bool a,b buttons) are working just fine. I'm attaching my test project to this post. I'm gonna test if the same problems happens on Oculus 2 controllers or if it is IndexController related.

    I've used:
    Steam VR 1.21.12 (beta)
    Unity 2021.2.19
     

    Attached Files:

    ROBYER1 likes this.
  18. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,450
    I can confirm after a lot of chain-rattling and yelling to the heavens, the controllers stuck together bug has been escalated internally at Unity - [OpenXR][SteamVR] Using Vive trackers causes the XR Controllers to be stuck together and not tracked separately

    Although, I no longer see this issue in my project using SteamVR beta, Maciej from the posts above has mentioned they still find the issue so I'm coordinating with them to identify if it is unique to their setup of Index vs my Vive setup.
     
  19. MaciejZareba_4experience

    MaciejZareba_4experience

    Joined:
    Mar 11, 2020
    Posts:
    21
    I confirmed that bug occur even when using Oculus Controllers. As long as you have HTC Vive Trackers Profile in project bug happens.
     
  20. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,450
    We now have reason to believe the OpenXR device ids for certain tracker profiles interferes with controllers tracking, I can confirm on my end that the Right Elbow tracker profile works fine in tandem with the Vive Controllers, but it seems the left/right foot in another project cause the left vive controller to be stuck in the middle of the scene while the right controller tracks. Will post back more findings when I have time.
     
  21. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,133
    Finally got some time to come back to this.

    Can confirm I have my index and both index controllers working with a vive tracker via Maciejs example. Initially both controllers were attached to the left hand, but this is because the actual 'RightHand' prefab is set up wrong and its bindings were referencing the right hand. I changed it so all the controller binding explicitly reference left and right hand correctly and it works just fine with a vive tracker also mapped to Left Foot. This is all on the latest SteamVR Beta.

    But now the issue remaining for me is I don't want to explicitly map vive trackers to body parts in the steamvr settings. In VRChat you don't have to change any steam settings pertaining to your vive trackers, it just detects all of them, then figures out if they should be left foot, right foot, elbow etc by it doing an initial calibration and seeing which tracker is nearest to which body part. This is the expected UX now because VRChat made full body tracking so popular. But currently there seems to be no way to get vive tracker data when the tracker is set to the default 'Held in Hand - Any Hand' setting. Need to find a way so all my vive trackers can be set to 'Held in hand - Any Hand' then the binding can be just the generic 'XR Tracker devicePosition / deviceRotation' and have them all be detected and usable over that binding.
     
    ROBYER1 likes this.
  22. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,133
    So as per the OpenXR spec here:
    The OpenXR Specification (khronos.org)

    I found I could add the user path '/user/vive_tracker_htcx/role/handheld_object" without error. But seem to not be able to get it to register as anything? I assume thats what vive trackers set to 'held in hand - any hand' should come through on?
     
    ROBYER1 likes this.
  23. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,450
    I would argue this is something you would write yourself, since SteamVR manages which trackers are assigned to which body part, you would then have two different identities for each tracker. If you wanted something like VR Chat just write it yourself in code to detect which trackers are nearest and use them for the body parts you want but in SteamVR of course they will still have their assignments which are different.
     
  24. pmem

    pmem

    Joined:
    Aug 4, 2019
    Posts:
    5
    Hi everyone, any news regarding this?
    I've fixed my previous code with the modifications you did and still I am getting no input in Unity (they are all listed)
    Tried restarting SteamVR beta, Unity, reconnect and reassign the tracker, but non of the listed trackers are receiving input. Also, *not* facing the bug of same position controllers when the extensions is enabled.
     
  25. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,133
    Well the problem is currently unity openxr just doesn't even detect trackers set to 'Held in Hand - Any Hand' so I couldn't do it entirely from Unity. The user would have first adjust steamvr settings.
     
  26. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,450
    Is there any way we can get 'Held in hand' to work? or is this convention not available in OpenXR I assume as all the other profiles pull through.
     
  27. MaciejZareba_4experience

    MaciejZareba_4experience

    Joined:
    Mar 11, 2020
    Posts:
    21
    Gonna try it tomorrow. If it is working it is big progress to me cuz i can finally support gloves and trackers input in my project at the same time.
     
  28. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,133
    I don't know. The OpenXR spec has Held In Hand in it, but SteamVR seems to not return any data for it. Its probably something Valve would need to debug or give us more info on.
     
    ROBYER1 likes this.
  29. MicahARL

    MicahARL

    Joined:
    May 29, 2020
    Posts:
    2
    For anyone who was having issues with the Input Debugger not receiving values from the trackers, try doing the following (in addition to everything else people recommended in this thread):

    1. Ensure each tracker is paired to a dongle, not the headset. These instructions should help you do that: https://forum.vive.com/topic/7413-how-to-unpair-all-controllers-peripherals-while-troubleshooting/

    2. Have at least one TrackedPoseDriver component in the scene with its position and rotation actions bound to a tracker w/ usage (e.g. <XRViveTracker>{Waist}/devicePosition).

    I cannot say for sure whether item 2 actually made a difference, but it was one of the changes I made between failure and success.

    I can verify it is working on two separate machines with the following environment:

    Hardware
    HTC Vive (original)
    Vive Tracker 2.0 (rev 2018) and 3.0

    Software
    Unity 2020.3.19f1, 2021.3.1f1, 2022.1.1f1
    SteamVR 1.21.12

    Packages
    Input System 1.3.0
    OpenXR Plugin 1.3.1, and 1.4.2
    XR Plugin Management 4.2.0

    I'd be happy to provide additional information if requested. I hope this helps someone who was stuck like me!
     
  30. A4VR

    A4VR

    Joined:
    Dec 19, 2016
    Posts:
    8
    Any updates on this topic ? I tried it with Unity 2021 and can't get it to work. Do I need to set them up with the dongles ? Why does't it work connected to the Headset ? We really want to upgrade our Experience to 2021 because DLSS is a huge performance boost. But our old Method fetching the devices like this:

    Code (CSharp):
    1.   var inputDevices = new List<UnityEngine.XR.InputDevice>();
    2.         UnityEngine.XR.InputDevices.GetDevices(inputDevices);
    does not work anymore.. It just finds the Headset as Device.
     
  31. pmem

    pmem

    Joined:
    Aug 4, 2019
    Posts:
    5
    Hello again ^^'

    So I have my code running pretty well, but I cannot get the trackers to work in the Build (they only work in the Editor). I see in the Debug that the extension is correctly enabled and that the trackers are added, but the actions are not triggered.

    EDIT: If I query the device manually with UnityEngine.InputSystem.InputSystem.GetDevice<XRTrackerSteam>(usage) I can read the values, so it must be a problem with the bindings. The controllers work correctly, so I'm not sure were the problem is... Maybe the ActionMap is being enabled before the devices are registered.. Would that be a problem?

    EDIT2: Following my implementation bellow, if I bind to XRTrackerVive it works, but if I bind to it's base type "XRTrackerSteam" it does not (works in Editor).

    This is the code I have to support the trackers:

    Code (CSharp):
    1. using System.Collections.Generic;
    2. #if UNITY_EDITOR
    3. using UnityEditor;
    4. #endif
    5. using UnityEngine;
    6. using UnityEngine.InputSystem;
    7. using UnityEngine.InputSystem.Layouts;
    8. using UnityEngine.InputSystem.XR;
    9. using UnityEngine.XR;
    10.  
    11. namespace MASSIVE.InputSystem.XR.OpenXR.SteamXRTracker
    12. {
    13.     /// <summary>
    14.     /// A tracker device that has its orientation and position in space tracked.
    15.     /// </summary>
    16. #if UNITY_EDITOR
    17.     [InitializeOnLoad]
    18. #endif
    19.     [InputControlLayout(displayName = "XR Tracker", isGenericTypeOfDevice = true)]
    20.     public class XRTracker : TrackedDevice
    21.     {
    22.  
    23.         static XRTracker()
    24.         {
    25.             UnityEngine.InputSystem.InputSystem.RegisterLayout<XRTracker>();
    26.         }
    27.  
    28.         [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    29.         private static void InitializeInPlayer() { }
    30.     }
    31.  
    32.  
    33. #if UNITY_EDITOR
    34.     [InitializeOnLoad]
    35. #endif
    36.     [InputControlLayout(displayName = "XR Tracker (Steam)", commonUsages = new string[] { TrackerCommonUsages.t_FootLeft, TrackerCommonUsages.t_FootRight, TrackerCommonUsages.t_ShoulderLeft,
    37.         TrackerCommonUsages.t_ShoulderRight, TrackerCommonUsages.t_ElbowLeft, TrackerCommonUsages.t_ElbowRight, TrackerCommonUsages.t_KneeLeft, TrackerCommonUsages.t_KneeRight, TrackerCommonUsages.t_Waist,
    38.         TrackerCommonUsages.t_Chest, TrackerCommonUsages.t_Camera, TrackerCommonUsages.t_Handheld, TrackerCommonUsages.t_Keyboard })]
    39.     public class XRTrackerSteam : XRTracker
    40.     {
    41.  
    42.         private static List<XRTrackerSteam> s_AllMyDevices = new List<XRTrackerSteam>();
    43.         public static new IReadOnlyList<XRTrackerSteam> all => s_AllMyDevices;
    44.  
    45.         static XRTrackerSteam()
    46.         {
    47.             UnityEngine.InputSystem.InputSystem.RegisterLayout<XRTrackerSteam>();
    48.         }
    49.  
    50.         [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    51.         private static void InitializeInPlayer() { }
    52.  
    53.  
    54.         protected override void OnAdded()
    55.         {
    56.             base.OnAdded();
    57.             s_AllMyDevices.Add(this);
    58.         }
    59.  
    60.         protected override void OnRemoved()
    61.         {
    62.             base.OnRemoved();
    63.             s_AllMyDevices.Remove(this);
    64.         }
    65.  
    66.         public static XRTrackerSteam GetXrTrackerDevice(string usage)
    67.         {
    68.             return UnityEngine.InputSystem.InputSystem.GetDevice<XRTrackerSteam>(usage);
    69.         }
    70.  
    71.  
    72.         protected override void FinishSetup()
    73.         {
    74.             base.FinishSetup();
    75.  
    76.             var capabilities = description.capabilities;
    77.             var deviceDescriptor = XRDeviceDescriptor.FromJson(capabilities);
    78.  
    79.  
    80.             if (deviceDescriptor != null)
    81.             {
    82.                 TrackerCharacteristics t = (TrackerCharacteristics)((int)deviceDescriptor.characteristics);
    83.  
    84.                 Debug.Log($"Adding XRTracker ({t})");
    85.  
    86.                 switch (t)
    87.                 {
    88.                     case TrackerCharacteristics.FootLeft:
    89.                         UnityEngine.InputSystem.InputSystem.SetDeviceUsage(this, TrackerCommonUsages.t_FootLeft);
    90.                         break;
    91.                     case TrackerCharacteristics.FootRight:
    92.                         UnityEngine.InputSystem.InputSystem.SetDeviceUsage(this, TrackerCommonUsages.t_FootRight);
    93.                         break;
    94.                     case TrackerCharacteristics.ShoulderLeft:
    95.                         UnityEngine.InputSystem.InputSystem.SetDeviceUsage(this, TrackerCommonUsages.t_ShoulderLeft);
    96.                         break;
    97.                     case TrackerCharacteristics.ShoulderRight:
    98.                         UnityEngine.InputSystem.InputSystem.SetDeviceUsage(this, TrackerCommonUsages.t_ShoulderRight);
    99.                         break;
    100.                     case TrackerCharacteristics.ElbowLeft:
    101.                         UnityEngine.InputSystem.InputSystem.SetDeviceUsage(this, TrackerCommonUsages.t_ElbowLeft);
    102.                         break;
    103.                     case TrackerCharacteristics.ElbowRight:
    104.                         UnityEngine.InputSystem.InputSystem.SetDeviceUsage(this, TrackerCommonUsages.t_ElbowRight);
    105.                         break;
    106.                     case TrackerCharacteristics.KneeLeft:
    107.                         UnityEngine.InputSystem.InputSystem.SetDeviceUsage(this, TrackerCommonUsages.t_KneeLeft);
    108.                         break;
    109.                     case TrackerCharacteristics.KneeRight:
    110.                         UnityEngine.InputSystem.InputSystem.SetDeviceUsage(this, TrackerCommonUsages.t_KneeRight);
    111.                         break;
    112.                     case TrackerCharacteristics.Waist:
    113.                         UnityEngine.InputSystem.InputSystem.SetDeviceUsage(this, TrackerCommonUsages.t_Waist);
    114.                         break;
    115.                     case TrackerCharacteristics.Chest:
    116.                         UnityEngine.InputSystem.InputSystem.SetDeviceUsage(this, TrackerCommonUsages.t_Chest);
    117.                         break;
    118.                     case TrackerCharacteristics.Camera:
    119.                         UnityEngine.InputSystem.InputSystem.SetDeviceUsage(this, TrackerCommonUsages.t_Camera);
    120.                         break;
    121.                     case TrackerCharacteristics.Handheld:
    122.                         UnityEngine.InputSystem.InputSystem.SetDeviceUsage(this, TrackerCommonUsages.t_Handheld);
    123.                         break;
    124.                     case TrackerCharacteristics.Keyboard:
    125.                         UnityEngine.InputSystem.InputSystem.SetDeviceUsage(this, TrackerCommonUsages.t_Keyboard);
    126.                         break;
    127.                     default:
    128.                         Debug.Log($"Added unknown XRTracker ({t})");
    129.                         break;
    130.                 }
    131.             }
    132.  
    133.         }
    134.  
    135.         public static class TrackerCommonUsages
    136.         {
    137.             public const string t_FootLeft = "Foot Left";
    138.             public const string t_FootRight = "Foot Right";
    139.             public const string t_ShoulderLeft = "Shoulder Left";
    140.             public const string t_ShoulderRight = "Shoulder Right";
    141.             public const string t_ElbowLeft = "Elbow Left";
    142.             public const string t_ElbowRight = "Elbow Right";
    143.             public const string t_KneeLeft = "Knee Left";
    144.             public const string t_KneeRight = "Knee Right";
    145.             public const string t_Waist = "Waist";
    146.             public const string t_Chest = "Chest";
    147.             public const string t_Camera = "Camera";
    148.             public const string t_Handheld = "Handheld Object";
    149.             public const string t_Keyboard = "Keyboard";
    150.         }
    151.  
    152.         public enum TrackerCharacteristics : uint
    153.         {
    154.             FootLeft = 1 << 12 | InputDeviceCharacteristics.TrackedDevice,
    155.             FootRight = 1 << 13 | InputDeviceCharacteristics.TrackedDevice,
    156.             ShoulderLeft = 1 << 14 | InputDeviceCharacteristics.TrackedDevice,
    157.             ShoulderRight = 1 << 15 | InputDeviceCharacteristics.TrackedDevice,
    158.             ElbowLeft = 1 << 16 | InputDeviceCharacteristics.TrackedDevice,
    159.             ElbowRight = 1 << 17 | InputDeviceCharacteristics.TrackedDevice,
    160.             KneeLeft = 1 << 18 | InputDeviceCharacteristics.TrackedDevice,
    161.             KneeRight = 1 << 19 | InputDeviceCharacteristics.TrackedDevice,
    162.             Waist = 1 << 20 | InputDeviceCharacteristics.TrackedDevice,
    163.             Chest = 1 << 21 | InputDeviceCharacteristics.TrackedDevice,
    164.             Camera = 1 << 22 | InputDeviceCharacteristics.TrackedDevice,
    165.             Handheld = 1 << 23 | InputDeviceCharacteristics.TrackedDevice, // TODO: Find Correct Bit and add Left+Right
    166.             Keyboard = 1 << 24 | InputDeviceCharacteristics.TrackedDevice,
    167.         }
    168.     }
    169. }
    170.  

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine.Scripting;
    3. using UnityEngine.XR.OpenXR.Input;
    4. using UnityEngine.InputSystem.Layouts;
    5. using UnityEngine.InputSystem.Controls;
    6. using UnityEngine.InputSystem.XR;
    7. using UnityEngine.InputSystem;
    8. using UnityEngine.XR.OpenXR;
    9. using UnityEngine.XR.OpenXR.Features;
    10. using UnityEngine.XR;
    11. using UnityEngine;
    12. using static MASSIVE.InputSystem.XR.OpenXR.SteamXRTracker.XRTrackerSteam;
    13. using MASSIVE.InputSystem.XR.OpenXR.SteamXRTracker;
    14.  
    15. #if UNITY_EDITOR
    16. using UnityEditor;
    17. #endif
    18.  
    19. using PoseControl = UnityEngine.XR.OpenXR.Input.PoseControl;
    20.  
    21. namespace MASSIVE.InputSystem.XR.OpenXR.Features.Interactions
    22. {
    23.     /// <summary>
    24.     /// This <see cref="OpenXRInteractionFeature"/> enables the use of HTC Vive Trackers interaction profiles in OpenXR.
    25.     /// </summary>
    26. #if UNITY_EDITOR
    27.     [UnityEditor.XR.OpenXR.Features.OpenXRFeature(
    28.         UiName = "HTC Vive Tracker Profile",
    29.         BuildTargetGroups = new[] { BuildTargetGroup.Standalone, BuildTargetGroup.WSA },
    30.         Company = "MASSIVE",
    31.         Desc = "Allows for mapping input to the HTC Vive Tracker interaction profile.",
    32.         DocumentationLink = Constants.k_DocumentationManualURL,
    33.         OpenxrExtensionStrings = HTCViveTrackerProfile.extensionName,
    34.         Version = "0.0.1",
    35.         Category = UnityEditor.XR.OpenXR.Features.FeatureCategory.Interaction,
    36.         FeatureId = featureId)]
    37. #endif
    38.     public class HTCViveTrackerProfile : OpenXRInteractionFeature
    39.     {
    40.         /// <summary>
    41.         /// The feature id string. This is used to give the feature a well known id for reference.
    42.         /// </summary>
    43.         public const string featureId = "pt.massive.openxr.feature.input.htcvivetracker";
    44.  
    45.         /// <summary>
    46.         /// The interaction profile string used to reference the <a href="https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#:~:text=in%20this%20case.-,VIVE%20Tracker%20interaction%20profile,-Interaction%20profile%20path">HTC Vive Tracker</a>.
    47.         /// </summary>
    48.         public const string profile = "/interaction_profiles/htc/vive_tracker_htcx";
    49.  
    50.         /// <summary>
    51.         /// The name of the OpenXR extension that supports the Vive Tracker
    52.         /// </summary>
    53.         public const string extensionName = "XR_HTCX_vive_tracker_interaction";
    54.  
    55.         private const string kDeviceLocalizedName = "HTC Vive Tracker OpenXR";
    56.  
    57.         /// <summary>
    58.         /// OpenXR user path definitions for the tracker.
    59.         /// </summary>
    60.         public static class TrackerUserPaths
    61.         {
    62.             /// <summary>
    63.             /// Path for user held in hand
    64.             /// </summary>
    65.             public const string held = "/user/vive_tracker_htcx/role/handheld_object";
    66.  
    67.             /// <summary>
    68.             /// Path for user left foot
    69.             /// </summary>
    70.             public const string leftFoot = "/user/vive_tracker_htcx/role/left_foot";
    71.  
    72.             /// <summary>
    73.             /// Path for user roght foot
    74.             /// </summary>
    75.             public const string rightFoot = "/user/vive_tracker_htcx/role/right_foot";
    76.  
    77.             /// <summary>
    78.             /// Path for user left shoulder
    79.             /// </summary>
    80.             public const string leftShoulder = "/user/vive_tracker_htcx/role/left_shoulder";
    81.  
    82.             /// <summary>
    83.             /// Path for user right shoulder
    84.             /// </summary>
    85.             public const string rightShoulder = "/user/vive_tracker_htcx/role/right_shoulder";
    86.  
    87.             /// <summary>
    88.             /// Path for user left elbow
    89.             /// </summary>
    90.             public const string leftElbow = "/user/vive_tracker_htcx/role/left_elbow";
    91.  
    92.             /// <summary>
    93.             /// Path for user right elbow
    94.             /// </summary>
    95.             public const string rightElbow = "/user/vive_tracker_htcx/role/right_elbow";
    96.  
    97.             /// <summary>
    98.             /// Path for user left knee
    99.             /// </summary>
    100.             public const string leftKnee = "/user/vive_tracker_htcx/role/left_knee";
    101.  
    102.             /// <summary>
    103.             /// Path for user right knee
    104.             /// </summary>
    105.             public const string rightKnee = "/user/vive_tracker_htcx/role/right_knee";
    106.  
    107.             /// <summary>
    108.             /// Path for user waist
    109.             /// </summary>
    110.             public const string waist = "/user/vive_tracker_htcx/role/waist";
    111.  
    112.             /// <summary>
    113.             /// Path for user chest
    114.             /// </summary>
    115.             public const string chest = "/user/vive_tracker_htcx/role/chest";
    116.  
    117.             /// <summary>
    118.             /// Path for user custom camera
    119.             /// </summary>
    120.             public const string camera = "/user/vive_tracker_htcx/role/camera";
    121.  
    122.             /// <summary>
    123.             /// Path for user keyboard
    124.             /// </summary>
    125.             public const string keyboard = "/user/vive_tracker_htcx/role/keyboard";
    126.         }
    127.  
    128.         /// <summary>
    129.         /// OpenXR component path definitions for the tracker.
    130.         /// </summary>
    131.         public static class TrackerComponentPaths
    132.         {
    133.             /// <summary>
    134.             /// Constant for a boolean interaction binding '.../input/system/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    135.             /// </summary>
    136.             public const string system = "/input/system/click";
    137.             /// <summary>
    138.             /// Constant for a boolean interaction binding '.../input/squeeze/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    139.             /// </summary>
    140.             public const string squeeze = "/input/squeeze/click";
    141.             /// <summary>
    142.             /// Constant for a boolean interaction binding '.../input/menu/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    143.             /// </summary>
    144.             public const string menu = "/input/menu/click";
    145.             /// <summary>
    146.             /// Constant for a float interaction binding '.../input/trigger/value' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    147.             /// </summary>
    148.             public const string trigger = "/input/trigger/value";
    149.             /// <summary>
    150.             /// Constant for a boolean interaction binding '.../input/trigger/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    151.             /// </summary>
    152.             public const string triggerClick = "/input/trigger/click";
    153.             /// <summary>
    154.             /// Constant for a Vector2 interaction binding '.../input/trackpad' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    155.             /// </summary>
    156.             public const string trackpad = "/input/trackpad";
    157.             /// <summary>
    158.             /// Constant for a boolean interaction binding '.../input/trackpad/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    159.             /// </summary>
    160.             public const string trackpadClick = "/input/trackpad/click";
    161.             /// <summary>
    162.             /// Constant for a boolean interaction binding '.../input/trackpad/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    163.             /// </summary>
    164.             public const string trackpadTouch = "/input/trackpad/touch";
    165.             /// <summary>
    166.             /// Constant for a pose interaction binding '.../input/grip/pose' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    167.             /// </summary>
    168.             public const string grip = "/input/grip/pose";
    169.             /// <summary>
    170.             /// Constant for a haptic interaction binding '.../output/haptic' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
    171.             /// </summary>
    172.             public const string haptic = "/output/haptic";
    173.         }
    174.  
    175.         /// <summary>
    176.         /// Registers the <see cref="ViveTracker"/> layout with the Input System.
    177.         /// </summary>
    178.         protected override void RegisterDeviceLayout()
    179.         {
    180.  
    181.             UnityEngine.InputSystem.InputSystem.RegisterLayout(typeof(XRViveTracker),
    182.                         matches: new InputDeviceMatcher()
    183.                         .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
    184.                         .WithProduct(kDeviceLocalizedName));
    185.         }
    186.  
    187.         /// <summary>
    188.         /// Removes the <see cref="ViveTracker"/> layout from the Input System.
    189.         /// </summary>
    190.         protected override void UnregisterDeviceLayout()
    191.         {
    192.             UnityEngine.InputSystem.InputSystem.RemoveLayout(nameof(XRViveTracker));
    193.         }
    194.  
    195.  
    196.         /// <inheritdoc/>
    197.         protected override void RegisterActionMapsWithRuntime()
    198.         {
    199.             ActionMapConfig actionMap = new ActionMapConfig()
    200.             {
    201.                 name = "htcvivetracker",
    202.                 localizedName = kDeviceLocalizedName,
    203.                 desiredInteractionProfile = profile,
    204.                 manufacturer = "HTC",
    205.                 deviceInfos = new List<DeviceConfig>()
    206.                 {
    207.                     new DeviceConfig()
    208.                     {
    209.                         characteristics = (InputDeviceCharacteristics)(int)TrackerCharacteristics.FootLeft,
    210.                         userPath = TrackerUserPaths.leftFoot
    211.                     },
    212.                     new DeviceConfig()
    213.                     {
    214.                         characteristics = (InputDeviceCharacteristics)(int)TrackerCharacteristics.FootRight,
    215.                         userPath = TrackerUserPaths.rightFoot
    216.                     },
    217.                     new DeviceConfig()
    218.                     {
    219.                         characteristics = (InputDeviceCharacteristics)(int)TrackerCharacteristics.ShoulderLeft,
    220.                         userPath = TrackerUserPaths.leftShoulder
    221.                     },
    222.                     new DeviceConfig()
    223.                     {
    224.                         characteristics = (InputDeviceCharacteristics)(int)TrackerCharacteristics.ShoulderRight,
    225.                         userPath = TrackerUserPaths.rightShoulder
    226.                     },
    227.                     new DeviceConfig()
    228.                     {
    229.                         characteristics = (InputDeviceCharacteristics)(int)TrackerCharacteristics.ElbowLeft,
    230.                         userPath = TrackerUserPaths.leftElbow
    231.                     },
    232.                     new DeviceConfig()
    233.                     {
    234.                         characteristics = (InputDeviceCharacteristics)(int)TrackerCharacteristics.ElbowRight,
    235.                         userPath = TrackerUserPaths.rightElbow
    236.                     },
    237.                     new DeviceConfig()
    238.                     {
    239.                         characteristics = (InputDeviceCharacteristics)(int)TrackerCharacteristics.KneeLeft,
    240.                         userPath = TrackerUserPaths.leftKnee
    241.                     },
    242.                     new DeviceConfig()
    243.                     {
    244.                         characteristics = (InputDeviceCharacteristics)(int)TrackerCharacteristics.KneeRight,
    245.                         userPath = TrackerUserPaths.rightKnee
    246.                     },
    247.                     new DeviceConfig()
    248.                     {
    249.                         characteristics = (InputDeviceCharacteristics)(int)TrackerCharacteristics.Waist,
    250.                         userPath = TrackerUserPaths.waist
    251.                     },
    252.                     new DeviceConfig()
    253.                     {
    254.                         characteristics = (InputDeviceCharacteristics)(int)TrackerCharacteristics.Chest,
    255.                         userPath = TrackerUserPaths.chest
    256.                     },
    257.                     new DeviceConfig()
    258.                     {
    259.                         characteristics = (InputDeviceCharacteristics)(int)TrackerCharacteristics.Camera,
    260.                         userPath = TrackerUserPaths.camera
    261.                     },
    262.                     new DeviceConfig()
    263.                     {
    264.                         characteristics = (InputDeviceCharacteristics)(int)TrackerCharacteristics.Handheld,
    265.                         userPath = TrackerUserPaths.held
    266.                     },
    267.                     new DeviceConfig()
    268.                     {
    269.                         characteristics = (InputDeviceCharacteristics)(int)TrackerCharacteristics.Keyboard,
    270.                         userPath = TrackerUserPaths.keyboard
    271.                     }
    272.                 },
    273.                 actions = new List<ActionConfig>()
    274.                 {
    275.                     //new ActionConfig()
    276.                     //{
    277.                     //    name = "grip",
    278.                     //    localizedName = "Grip",
    279.                     //    type = ActionType.Axis1D,
    280.                     //    usages = new List<string>()
    281.                     //    {
    282.                     //        "Grip"
    283.                     //    },
    284.                     //    bindings = new List<ActionBinding>()
    285.                     //    {
    286.                     //        new ActionBinding()
    287.                     //        {
    288.                     //            interactionPath = TrackerComponentPaths.squeeze,
    289.                     //            interactionProfileName = profile,
    290.                     //        }
    291.                     //    }
    292.                     //},
    293.                     //new ActionConfig()
    294.                     //{
    295.                     //    name = "gripPressed",
    296.                     //    localizedName = "Grip Pressed",
    297.                     //    type = ActionType.Binary,
    298.                     //    usages = new List<string>()
    299.                     //    {
    300.                     //        "GripButton"
    301.                     //    },
    302.                     //    bindings = new List<ActionBinding>()
    303.                     //    {
    304.                     //        new ActionBinding()
    305.                     //        {
    306.                     //            interactionPath = TrackerComponentPaths.squeeze,
    307.                     //            interactionProfileName = profile,
    308.                     //        }
    309.                     //    }
    310.                     //},
    311.                     //new ActionConfig()
    312.                     //{
    313.                     //    name = "menu",
    314.                     //    localizedName = "Menu",
    315.                     //    type = ActionType.Binary,
    316.                     //    usages = new List<string>()
    317.                     //    {
    318.                     //        "MenuButton"
    319.                     //    },
    320.                     //    bindings = new List<ActionBinding>()
    321.                     //    {
    322.                     //        new ActionBinding()
    323.                     //        {
    324.                     //            interactionPath = TrackerComponentPaths.menu,
    325.                     //            interactionProfileName = profile,
    326.                     //        }
    327.                     //    }
    328.                     //},
    329.                     //new ActionConfig()
    330.                     //{
    331.                     //    name = "select",
    332.                     //    localizedName = "Select",
    333.                     //    type = ActionType.Binary,
    334.                     //    usages = new List<string>()
    335.                     //    {
    336.                     //        "SystemButton"
    337.                     //    },
    338.                     //    bindings = new List<ActionBinding>()
    339.                     //    {
    340.                     //        new ActionBinding()
    341.                     //        {
    342.                     //            interactionPath = TrackerComponentPaths.system,
    343.                     //            interactionProfileName = profile,
    344.                     //        }
    345.                     //    }
    346.                     //},
    347.                     //new ActionConfig()
    348.                     //{
    349.                     //    name = "trigger",
    350.                     //    localizedName = "Trigger",
    351.                     //    type = ActionType.Axis1D,
    352.                     //    usages = new List<string>()
    353.                     //    {
    354.                     //        "Trigger"
    355.                     //    },
    356.                     //    bindings = new List<ActionBinding>()
    357.                     //    {
    358.                     //        new ActionBinding()
    359.                     //        {
    360.                     //            interactionPath = TrackerComponentPaths.trigger,
    361.                     //            interactionProfileName = profile,
    362.                     //        }
    363.                     //    }
    364.                     //},
    365.                     //new ActionConfig()
    366.                     //{
    367.                     //    name = "triggerPressed",
    368.                     //    localizedName = "Trigger Pressed",
    369.                     //    type = ActionType.Binary,
    370.                     //    usages = new List<string>()
    371.                     //    {
    372.                     //        "TriggerButton"
    373.                     //    },
    374.                     //    bindings = new List<ActionBinding>()
    375.                     //    {
    376.                     //        new ActionBinding()
    377.                     //        {
    378.                     //            interactionPath = TrackerComponentPaths.triggerClick,
    379.                     //            interactionProfileName = profile,
    380.                     //        }
    381.                     //    }
    382.                     //},
    383.                     //new ActionConfig()
    384.                     //{
    385.                     //    name = "trackpad",
    386.                     //    localizedName = "Trackpad",
    387.                     //    type = ActionType.Axis2D,
    388.                     //    usages = new List<string>()
    389.                     //    {
    390.                     //        "Primary2DAxis"
    391.                     //    },
    392.                     //    bindings = new List<ActionBinding>()
    393.                     //    {
    394.                     //        new ActionBinding()
    395.                     //        {
    396.                     //            interactionPath = TrackerComponentPaths.trackpad,
    397.                     //            interactionProfileName = profile,
    398.                     //        }
    399.                     //    }
    400.                     //},
    401.                     //new ActionConfig()
    402.                     //{
    403.                     //    name = "trackpadTouched",
    404.                     //    localizedName = "Trackpad Touched",
    405.                     //    type = ActionType.Binary,
    406.                     //    usages = new List<string>()
    407.                     //    {
    408.                     //        "Primary2DAxisTouch"
    409.                     //    },
    410.                     //    bindings = new List<ActionBinding>()
    411.                     //    {
    412.                     //        new ActionBinding()
    413.                     //        {
    414.                     //            interactionPath = TrackerComponentPaths.trackpadTouch,
    415.                     //            interactionProfileName = profile,
    416.                     //        }
    417.                     //    }
    418.                     //},
    419.                     //new ActionConfig()
    420.                     //{
    421.                     //    name = "trackpadClicked",
    422.                     //    localizedName = "Trackpad Clicked",
    423.                     //    type = ActionType.Binary,
    424.                     //    usages = new List<string>()
    425.                     //    {
    426.                     //        "Primary2DAxisClick"
    427.                     //    },
    428.                     //    bindings = new List<ActionBinding>()
    429.                     //    {
    430.                     //        new ActionBinding()
    431.                     //        {
    432.                     //            interactionPath = TrackerComponentPaths.trackpadClick,
    433.                     //            interactionProfileName = profile,
    434.                     //        }
    435.                     //    }
    436.                     //},
    437.                     new ActionConfig()
    438.                     {
    439.                         name = "devicePose",
    440.                         localizedName = "Device Pose",
    441.                         type = ActionType.Pose,
    442.                         usages = new List<string>()
    443.                         {
    444.                             "Device"
    445.                         },
    446.                         bindings = new List<ActionBinding>()
    447.                         {
    448.                             new ActionBinding()
    449.                             {
    450.                                 interactionPath = TrackerComponentPaths.grip,
    451.                                 interactionProfileName = profile,
    452.                             }
    453.                         }
    454.                     },
    455.                     //// Haptics
    456.                     //new ActionConfig()
    457.                     //{
    458.                     //    name = "haptic",
    459.                     //    localizedName = "Haptic Output",
    460.                     //    type = ActionType.Vibrate,
    461.                     //    usages = new List<string>() { "Haptic" },
    462.                     //    bindings = new List<ActionBinding>()
    463.                     //    {
    464.                     //        new ActionBinding()
    465.                     //        {
    466.                     //            interactionPath = TrackerComponentPaths.haptic,
    467.                     //            interactionProfileName = profile,
    468.                     //        }
    469.                     //    }
    470.                     //}
    471.                 }
    472.             };
    473.  
    474.             AddActionMap(actionMap);
    475.         }
    476.  
    477.         protected override bool OnInstanceCreate(ulong xrInstance)
    478.         {
    479.             bool res = base.OnInstanceCreate(xrInstance);
    480.  
    481.             if (OpenXRRuntime.IsExtensionEnabled("XR_HTCX_vive_tracker_interaction"))
    482.             {
    483.                 Debug.Log("HTC Vive Tracker Extension Enabled");
    484.             }
    485.             else
    486.             {
    487.                 Debug.Log("HTC Vive Tracker Extension Not Enabled");
    488.             }
    489.  
    490.             return res;
    491.         }
    492.  
    493.         /// <summary>
    494.         /// An Input System device based off the <a href="https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#_htc_vive_controller_profile">HTC Vive Tracker</a>.
    495.         /// </summary>
    496.         [Preserve, InputControlLayout(displayName = "HTC Vive Tracker (OpenXR)", commonUsages = new string[] { TrackerCommonUsages.t_FootLeft, TrackerCommonUsages.t_FootRight, TrackerCommonUsages.t_ShoulderLeft,
    497.         TrackerCommonUsages.t_ShoulderRight, TrackerCommonUsages.t_ElbowLeft, TrackerCommonUsages.t_ElbowRight, TrackerCommonUsages.t_KneeLeft, TrackerCommonUsages.t_KneeRight, TrackerCommonUsages.t_Waist,
    498.         TrackerCommonUsages.t_Chest, TrackerCommonUsages.t_Camera, TrackerCommonUsages.t_Handheld, TrackerCommonUsages.t_Keyboard })]
    499.         public class XRViveTracker : XRTrackerSteam
    500.         {
    501.    
    502.  
    503.             /// <summary>
    504.             /// A <see cref="PoseControl"/> that represents information from the <see cref="HTCViveControllerProfile.grip"/> OpenXR binding.
    505.             /// </summary>
    506.             [Preserve, InputControl(offset = 0, aliases = new[] { "device", "gripPose" }, usage = "Device")]
    507.             public PoseControl devicePose { get; private set; }
    508.  
    509.             /// <summary>
    510.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) required for backwards compatibility with the XRSDK layouts. This represents the overall tracking state of the device. This value is equivalent to mapping devicePose/isTracked.
    511.             /// </summary>
    512.             [Preserve, InputControl(offset = 0)]
    513.             new public ButtonControl isTracked { get; private set; }
    514.  
    515.             /// <summary>
    516.             /// A [IntegerControl](xref:UnityEngine.InputSystem.Controls.IntegerControl) required for back compatibility with the XRSDK layouts. This represents the bit flag set indicating what data is valid. This value is equivalent to mapping devicePose/trackingState.
    517.             /// </summary>
    518.             [Preserve, InputControl(offset = 4)]
    519.             new public IntegerControl trackingState { get; private set; }
    520.  
    521.             /// <summary>
    522.             /// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for back compatibility with the XRSDK layouts. This is the device position. For the Oculus Touch device, this is both the grip and the pointer position. This value is equivalent to mapping devicePose/position.
    523.             /// </summary>
    524.             [Preserve, InputControl(offset = 8, alias = "gripPosition")]
    525.             new public Vector3Control devicePosition { get; private set; }
    526.  
    527.             /// <summary>
    528.             /// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the device orientation. For the Oculus Touch device, this is both the grip and the pointer rotation. This value is equivalent to mapping devicePose/rotation.
    529.             /// </summary>
    530.             [Preserve, InputControl(offset = 20, alias = "gripOrientation")]
    531.             new public QuaternionControl deviceRotation { get; private set; }
    532.  
    533.             /// <summary>
    534.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the HTC Vive Controller Profile select OpenXR binding.
    535.             /// </summary>
    536.             [Preserve, InputControl(aliases = new[] { "Secondary", "selectbutton" }, usage = "SystemButton")]
    537.             public ButtonControl select { get; private set; }
    538.  
    539.             /// <summary>
    540.             /// A [AxisControl](xref:UnityEngine.InputSystem.Controls.AxisControl) that represents information from the <see cref="HTCViveControllerProfile.squeeze"/> OpenXR binding.
    541.             /// </summary>
    542.             [Preserve, InputControl(aliases = new[] { "GripAxis", "squeeze" }, usage = "Grip")]
    543.             public AxisControl grip { get; private set; }
    544.  
    545.             /// <summary>
    546.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the <see cref="HTCViveControllerProfile.squeeze"/> OpenXR binding.
    547.             /// </summary>
    548.             [Preserve, InputControl(aliases = new[] { "GripButton", "squeezeClicked" }, usage = "GripButton")]
    549.             public ButtonControl gripPressed { get; private set; }
    550.  
    551.             /// <summary>
    552.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the <see cref="HTCViveControllerProfile.menu"/> OpenXR binding.
    553.             /// </summary>
    554.             [Preserve, InputControl(aliases = new[] { "Primary", "menubutton" }, usage = "MenuButton")]
    555.             public ButtonControl menu { get; private set; }
    556.  
    557.             /// <summary>
    558.             /// A [AxisControl](xref:UnityEngine.InputSystem.Controls.AxisControl) that represents information from the <see cref="HTCViveControllerProfile.trigger"/> OpenXR binding.
    559.             /// </summary>
    560.             [Preserve, InputControl(alias = "triggeraxis", usage = "Trigger")]
    561.             public AxisControl trigger { get; private set; }
    562.  
    563.             /// <summary>
    564.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the <see cref="HTCViveControllerProfile.triggerClick"/> OpenXR binding.
    565.             /// </summary>
    566.             [Preserve, InputControl(alias = "triggerbutton", usage = "TriggerButton")]
    567.             public ButtonControl triggerPressed { get; private set; }
    568.  
    569.             /// <summary>
    570.             /// A [Vector2Control](xref:UnityEngine.InputSystem.Controls.Vector2Control) that represents information from the <see cref="HTCViveControllerProfile.trackpad"/> OpenXR binding.
    571.             /// </summary>
    572.             [Preserve, InputControl(aliases = new[] { "Primary2DAxis", "touchpadaxes", "touchpad" }, usage = "Primary2DAxis")]
    573.             public Vector2Control trackpad { get; private set; }
    574.  
    575.             /// <summary>
    576.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the <see cref="HTCViveControllerProfile.trackpadClick"/> OpenXR binding.
    577.             /// </summary>
    578.             [Preserve, InputControl(aliases = new[] { "joystickorpadpressed", "touchpadpressed" }, usage = "Primary2DAxisClick")]
    579.             public ButtonControl trackpadClicked { get; private set; }
    580.  
    581.             /// <summary>
    582.             /// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the <see cref="HTCViveControllerProfile.trackpadTouch"/> OpenXR binding.
    583.             /// </summary>
    584.             [Preserve, InputControl(aliases = new[] { "joystickorpadtouched", "touchpadtouched" }, usage = "Primary2DAxisTouch")]
    585.             public ButtonControl trackpadTouched { get; private set; }
    586.  
    587.             /// <summary>
    588.             /// A <see cref="HapticControl"/> that represents the <see cref="HTCViveControllerProfile.haptic"/> binding.
    589.             /// </summary>
    590.             [Preserve, InputControl(usage = "Haptic")]
    591.             public HapticControl haptic { get; private set; }
    592.  
    593.             /// <inheritdoc cref="OpenXRDevice"/>
    594.             protected override void FinishSetup()
    595.             {
    596.                 base.FinishSetup();
    597.  
    598.                 devicePose = GetChildControl<PoseControl>("devicePose");
    599.                 devicePosition = GetChildControl<Vector3Control>("devicePosition");
    600.                 deviceRotation = GetChildControl<QuaternionControl>("deviceRotation");
    601.                 isTracked = GetChildControl<ButtonControl>("isTracked");
    602.                 trackingState = GetChildControl<IntegerControl>("trackingState");
    603.  
    604.                 select = GetChildControl<ButtonControl>("select");
    605.                 grip = GetChildControl<AxisControl>("grip");
    606.                 gripPressed = GetChildControl<ButtonControl>("gripPressed");
    607.                 menu = GetChildControl<ButtonControl>("menu");
    608.                 trigger = GetChildControl<AxisControl>("trigger");
    609.                 triggerPressed = GetChildControl<ButtonControl>("triggerPressed");
    610.                 trackpad = GetChildControl<Vector2Control>("trackpad");
    611.                 trackpadClicked = GetChildControl<ButtonControl>("trackpadClicked");
    612.                 trackpadTouched = GetChildControl<ButtonControl>("trackpadTouched");
    613.                 haptic = GetChildControl<HapticControl>("haptic");
    614.             }
    615.         }
    616.     }
    617.  
    618.  
    619. }
    620.  
     
    Last edited: Jun 6, 2022
  32. MaciejZareba_4experience

    MaciejZareba_4experience

    Joined:
    Mar 11, 2020
    Posts:
    21
    Sorry for delay. I have followed your solution and it is working (cant belive i've missed somthing so obvious). Here is working copy of test scene with separated contorllers.

    Update: I've confirmed it is working in builds.
     

    Attached Files:

    devanshgupta0110 likes this.
  33. kkkey21

    kkkey21

    Joined:
    May 14, 2020
    Posts:
    1
    Hello! May I ask why am I having this issue?
    Assets\Scripts\HTCViveTrackerProfile.cs(28,39): error CS0117: 'Constants' does not contain a definition for 'k_DocumentationManualURL'
     
  34. Petr_Raunigr

    Petr_Raunigr

    Joined:
    Apr 20, 2021
    Posts:
    6
    Hello,

    I read through the whole discussion and I didn't find any solution for my problem so here I am... :))

    I have two HTC Vive tracker 3.0 and I am facing the same issue people were dealing with controllers... the left tracker is fine, the right one is stick to the left tracker. I tried the sample scene (fixed version) and it also happens here.

    • I checked bindings in the project, all is correct.
    • I also double checked that my trackers are marked as left foot and right foot.
    • My OpenXR Runtime is not SteamVR's but Varjo's.
    • I tried SteamVR Beta version with no luck.

    Did I miss something?
     
  35. Petr_Raunigr

    Petr_Raunigr

    Joined:
    Apr 20, 2021
    Posts:
    6
    @thep3000, @pmem, @ROBYER1

    Do you have any recommendation, please? I am starting to be a bit desperate about this so I'm sorry for tagging you, I just wanted to be sure you noticed :))

    Thanks.
     
  36. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,450
  37. BradFichter

    BradFichter

    Joined:
    Nov 17, 2016
    Posts:
    5
    Hi, I have been reading and working for days to get the data to come through WITHOUT a headset. Null driver set, etc. Everything looks like it is set up correctly but no data coming through the input analysis tool. (note: tracking works fine w/o headset in Unreal using linking)
     
    sametkurumahmut likes this.
  38. alpay_unity821

    alpay_unity821

    Joined:
    Nov 22, 2022
    Posts:
    2
    i got here after trying to follow this video


    and I failed :( Is the best option to use an old version of Unity and just go for the old school official SteamVR asset in the store?
     
  39. vice39

    vice39

    Joined:
    Nov 11, 2016
    Posts:
    108
    I have exactly the same problem. It doesn't work if you don't have a headset connect (NULL driver).
     
  40. vice39

    vice39

    Joined:
    Nov 11, 2016
    Posts:
    108
    I also can't get this to work. Without a headset I never get any data from the tracker.
     
  41. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,450
    When can we see connect/disconnect events for trackers?
     
  42. alpay_unity821

    alpay_unity821

    Joined:
    Nov 22, 2022
    Posts:
    2
  43. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    851
    I don't think there is a "correct" version. But I can confirm that 2021.3 LTS and works fine. Have not tried later versions, but earlier versions like 2020 LTS and 2019 LTS also do work.
     
  44. CBHM

    CBHM

    Joined:
    Feb 12, 2019
    Posts:
    32
    Hi @ROBYER1, @MaciejZareba_4experience

    I am facing a similar issue where having the htcViveTrackerProfile under the interaction profile along with the oculus interaction profile throws an error: "Failed to create Action 'htcvivetracker/devicepose' with result 'XR_ERROR_PATH_UNSUPPORTED'" and the oculus controller don't work nor they show up in the input debugger when OpenXR runtime is set to Oculus.

    I am using the XRI default input action from the sample starter asset.

    HTC Vive Tracker Profile I am using which works fine with Valve Index and HTC Vive:
    https://forum.unity.com/attachments/htcvivetrackerprofile-cs.986229/

    Input debugger and error log

    upload_2023-1-9_18-8-55.png


    Interaction Profiles:

    upload_2023-1-9_18-3-13.png

    Scene Setup and XRControllers:

    upload_2023-1-9_18-4-15.png

    Left-Hand Input Actions:

    upload_2023-1-9_18-4-42.png

    Right-Hand Input Actions:

    upload_2023-1-9_18-5-7.png

    • Unity Version: 2020.3.35f1
    • OpenXR plugin: 1.4.2
    • Oculus XR plugin: 1.12.1
    • Input System: 1.3.0
    • XR interaction toolkit: 2.2.0
    Is there something I am missing, I apologize for tagging you, and thank you.
     
  45. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,450
    @CBHM Use SteamVR as default OpenXR runtime. You can mix the devices there. With Oculus as OpenXR runtime, Vive trackers won't work but SteamVR as OpenXR default will let you use Oculus and HTC devices together usually or at least with common workarounds.
     
  46. CBHM

    CBHM

    Joined:
    Feb 12, 2019
    Posts:
    32
    @ROBYER1 Thank you! I will give that a try, but we want users to be able to use Oculus app if they want, I am also looking into enabling an interaction profile at runtime. e.g. only enable the trackerProfile if the runtime is SteamVR.
     
  47. ROBYER1

    ROBYER1

    Joined:
    Oct 9, 2015
    Posts:
    1,450
    Yep, the choice of OpenXR Runtime is down to the user and not all of them support the same OpenXR features unfortunately. Finding out if the user is using Oculus somehow would be cool to prevent users trying to use trackers.
     
    CBHM likes this.
  48. VRDave_Unity

    VRDave_Unity

    Unity Technologies

    Joined:
    Nov 19, 2021
    Posts:
    260
    In terms of detecting which runtime is active, the OpenXR spec still doesn't provide an extension/API to get that information. However, on Windows machines, you can query the registry to find which one is active. We have some internal tooling in the OpenXR package which handles this (look at the package file
    com.unity.xr.openxr/Editor/OpenXRRuntimeSelector.cs
    ). However, the important bit I have encapsulated in this simple script:
    Code (CSharp):
    1. using System;
    2. using Microsoft.Win32;
    3. using UnityEngine;
    4.  
    5. public class CheckOpenXRRuntime : MonoBehaviour
    6. {
    7.     const string k_OculusRuntime = "oculus";
    8.     const string k_SteamVRRuntime = "steamvr";
    9.     const string k_WindowsMR = "mixedrealityruntime";
    10.  
    11.     void Start()
    12.     {
    13.         try
    14.         {
    15.             var runtime = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\OpenXR\1", "ActiveRuntime", "").ToString().ToLower();
    16.  
    17.             if (runtime.Contains(k_OculusRuntime))
    18.                 Debug.Log("Detected Oculus Runtime");
    19.             else if (runtime.Contains(k_SteamVRRuntime))
    20.                 Debug.Log("Detected SteamVR Runtime");
    21.             else if (runtime.Contains(k_WindowsMR))
    22.                 Debug.Log("Detected Windows MR Runtime");
    23.             else
    24.                 Debug.LogWarning($"Unknown OpenXR Runtime detected { runtime }");
    25.         }
    26.         catch (Exception ex)
    27.         {
    28.             Debug.LogError($"Error reading from registry: { ex.Message }", this);
    29.         }
    30.     }
    31. }
    32.  
    You'll have to add your own magic to it to trigger events/change input actions/etc.
     
    CBHM likes this.
  49. CBHM

    CBHM

    Joined:
    Feb 12, 2019
    Posts:
    32
    Thank you so much for your help, VRDave_Unity and Robyer. Enabling the trackerProfile based on the active runtime worked for me.
     
  50. BenWoodford

    BenWoodford

    Joined:
    Sep 29, 2013
    Posts:
    116
    I don't suppose you could put a license (ideally MIT if you're happy to do so) against this are you? So that others can use it without worry about licensing.