Detecting headset unmount with OpenXR
This might be obvious to some, but for someone unfamiliar with the new input system, like me, it can be a bit confusing.
Background
If you do public events and show XR demos, you know the drill: show the demo, get the device back, reset the app, and give it to the next person. In our current WIRKsam project, most of our demos are planned to be public, so I wanted to build a way to handle pass-overs gracefully. The main idea is to reset the app automatically when the user takes the headset off. If you’re using Oculus libraries, it’s as simple as this:
1
2
OVRManager.HMDMounted += () => { /* Do stuff */ };
OVRManager.HMDUnmounted += () => { /* Do stuff */ };
However, in this project, I am using OpenXR, which requires a bit more effort.
Binding the Action
As of the OpenXR 1.11 package in Unity, OpenXRUtility.IsUserPresent
returns whether the user is wearing the headset or not, as long as it is supported by the device, which is a good start. However, unlike Oculus, OpenXR does not define a similar event, so you’ll need to listen for it as an input.
First, open your inputactions
file and add an action. Set the type to “Button.” Then select
Listening the Action
Here’s a component for listening to the action:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
using UnityEngine;
using UnityEngine.InputSystem;
public class PresenceListener : MonoBehaviour
{
public InputActionAsset inputActions;
private InputAction userPresenceAction;
private void OnEnable()
{
userPresenceAction = inputActions.FindAction("UserPresence");
if (userPresenceAction != null)
{
userPresenceAction.performed += OnDeviceMounted;
userPresenceAction.canceled += OnDeviceUnmounted;
userPresenceAction.Enable();
}
}
private void OnDisable()
{
// Unsubscribe when the object is disabled or destroyed
if (userPresenceAction != null)
{
userPresenceAction.performed -= OnDeviceMounted;
userPresenceAction.canceled -= OnDeviceUnmounted;
userPresenceAction.Disable();
}
}
private void OnDeviceMounted(InputAction.CallbackContext context)
{
// Do sth
}
private void OnDeviceUnmounted(InputAction.CallbackContext context)
{
// Do sth
}
}
Small warning
This, of course, still depends on if the device supports the feature or not. In my experience, it works for Quest Pro and Quest 3, but other devices might give different results. Also, make sure to use the latest OpenXR package, as previous versions had some reported bugs related to this feature.