Search Unity

Bug OpenXR userPresence [XR HMD] input binding incorrectly returning false

Discussion in 'VR' started by emrys90, Apr 22, 2022.

  1. emrys90

    emrys90

    Joined:
    Oct 14, 2013
    Posts:
    755
    When the game is launched with the headset on with SteamVR as the OpenXR runtime then userPresence returns false until the player takes the headset off and puts it back on. This issue does not happen with Oculus as the OpenXR runtime.

    Any ideas on how to work around this issue? I need to wait to execute an action until the player is wearing the headset.
     
    Last edited: Apr 22, 2022
  2. runeberg-valve

    runeberg-valve

    Joined:
    Jan 28, 2020
    Posts:
    34
  3. emrys90

    emrys90

    Joined:
    Oct 14, 2013
    Posts:
    755
    Pause when off sounds like the opposite of what we are trying to do? All we want is an accurate way to know if the player is wearing the headset or not.
     
  4. runeberg-valve

    runeberg-valve

    Joined:
    Jan 28, 2020
    Posts:
    34
    My understanding is that Unity used the session states to get userPresence. For SteamVR, you can unset the "Pause when VR headset is Idle" if you wish to bypass this.

    If you want to keep it as is, then yeah, keep it set to "On". But you'll still need to use the Beta as we recently sent out a fix for this.
     
    Last edited: May 4, 2022
  5. emrys90

    emrys90

    Joined:
    Oct 14, 2013
    Posts:
    755
    Sorry if I am misunderstanding this, but you are saying the solution is a setting that each player would have to individually change? That isn't a solution if so. This works perfectly in the Oculus runtime. It's only a SteamVR bug, and only if the headset is already being worn when the game launches.
     
  6. runeberg-valve

    runeberg-valve

    Joined:
    Jan 28, 2020
    Posts:
    34
    There is no "userPresence" in OpenXR, this is a Unity implementation simply interpreting the current openxr session state.

    SteamVR exposes settings for individual users to override the hmd timeout behaviour (headset when Idle) which impacts the openxr session state, and we allow end users to set these timeouts (or lack thereof) as they prefer - this is not a mandated OpenXR behavior.

    The only expected runtime behaviour as per the specification is for the openxr session state to be in what's called the "focused" state when accepting input and the headset is rendering. Focused state in my understanding equals to "true" for what Unity is calling "userPresence" (m_CurrentSessionState == XR_SESSION_STATE_FOCUSED).

    SteamVR Beta has a fix that ensures the correct session state is returned - when you hit Play, the headset will render and accept input (focused state : true) whether or not the headset is on a person's head until the set timeout in SteamVR Settings. If a timeout is reached and the headset isn't worn, the openxr session state switches to "Synchronized" which Unity's plugin calls as userPresence = "false".

    Have you tried using the Beta though? The default for "Pause when VR headset is Idle" is true which should align with what I think you are expecting, however end users have the ability, yes, to override this.

    Depending on what you need the info for, a solution can be is to read the openxr session state (should be made available in the unity plugin if not), which should give you more granular info on what the headset is currently doing (rendering, accepting input, idle, etc):
    https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#session-states

    Another potential solution for this is to have an OpenXR extension that explicitly defines hmd proximity results. This is something I believe that Unity is already aware of, and can also be directly raised/echoed in the Khronos forums for better visibility with the OpenXR working group who can initiate and effect these changes:
    https://community.khronos.org/c/openxr/25
     
    Last edited: May 4, 2022
  7. runeberg-valve

    runeberg-valve

    Joined:
    Jan 28, 2020
    Posts:
    34
    Checked with Unity, and the correct way of reading that value is via something like this:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.InputSystem;
    using UnityEngine.UI;
    using UnityEngine.XR.Management;
    using UnityEngine.XR.OpenXR.Input;

    public class debugInput : MonoBehaviour
    {
    [Tooltip("Action Reference that represents the control")]
    [SerializeField] private InputActionReference _actionReference = null;

    // Start is called before the first frame update
    void Start()
    {
    Debug.Log(_actionReference.action.ReadValue<float>());
    }

    // Update is called once per frame
    void Update()
    {
    Debug.Log(_actionReference.action.ReadValue<float>());
    }
    }

    As action type "Button" the "Initial State Check" should also be enabled. I noticed older version of Unity does have the issue, but if you update to the latest LTS you should be getting the correct values.
     
  8. emrys90

    emrys90

    Joined:
    Oct 14, 2013
    Posts:
    755
    If this is a bug with Unity or how I am reading the value, then why does it work correctly with the Oculus OpenXR runtime?
     
  9. runeberg-valve

    runeberg-valve

    Joined:
    Jan 28, 2020
    Posts:
    34
    iirc you were using _userPresenceAction.action.phase == InputActionPhase.Performed after 5 seconds of your game starting? "Performed" happens on the change of state, so there's a chance you might be missing the state change.
     
    zsottyahu likes this.
  10. Ikaro88

    Ikaro88

    Joined:
    Jun 6, 2016
    Posts:
    300
    did you solved?
     
  11. djhatvr

    djhatvr

    Joined:
    Sep 22, 2019
    Posts:
    53
    This is a bug:

    If I pool the User Presence action I continue to get a 1.0 after I take off the headset.
    I only get a 0.0 when I put the head set back on. I get a string of maybe 30 0.0's and then back to 1.0

    The value doesn't get updated while the headset is off and so the 0.0 doesn't show up until the headset is back on.
    This is probably why the UserPresence.canceled event only triggers when the head set is put back on
     
  12. SeanBlissett

    SeanBlissett

    Joined:
    Oct 14, 2014
    Posts:
    2
    I am running into this same issue.

    It seems like the user presence or more generally the input device for the headset does correctly update the values except for when the headset is dismounted. The headset input device does not display the updated values while off, but when placed back on all of the values that changed rapidly are applied. Just like djhatvr's example.

    Anyone have any idea why the input device for the headset stops updating while dismounted? It feels like it shouldn't be doing this so that the user presence could be allowed to change to 0.