XR OnControllerConnect & OnControllerDisconnect

How can I determine if a XR controller is connected or not?

I have tried two methods so far, without success.

  1. I tried to get this information from a instance of “XRBaseController”, but I cant find a way to see if a controller is connected.
    2.Made use of InputDevices.GetDevicesAtXRNode. With this I can see when a controller is connected, but it doesn’t seem to be able to tell me if a controller gets turned off.
void Update()
{
        List<InputDevice> xrInputDevices = new List<InputDevice>();
        InputDevices.GetDevicesAtXRNode(XRNode.RightHand, xrInputDevices);
        bool isControllerConnected= false;
        for (int i = 0; i < xrInputDevices.Count; ++i)
            if (xrInputDevices[i].isValid)
                isControllerConnected= true;
        this.isControllerConnected = isControllerConnected;
}

I believe this is exactly what you are looking for::

XR Input under section Listening for device connections and disconnections:
(Unity - Manual: Unity XR Input)

“To avoid repeatedly checking if a device is connected to the platform, use InputDevices.deviceConnected and InputDevices.deviceDisconnected to notify your application when a device connects or disconnects.”

Then, all you should need is this:

/* If you want to set "isControllerConnected" if the first device matches the XRNode:: */
InputDevice xrInputDevice;
bool isControllerConnected;
IEnumerator Start()
{
     // Get target devices
     List<InputDevice>() xrInputDevices = new List<InputDevice>();
     InputDevices.GetDevicesAtXRNode(XRNode.RightHand, xrInputDevices);
     while (xrInputDevices.Count <= 0)
     {
          // wait for a device to be found.
          yield return null;
          InputDevices.GetDevicesAtXRNode(XRNode.RightHand, xrInputDevices);
     }
     xrInputDevice = xrInputDevices[0];

     // Initialize if controller is connected
     isControllerConnected = xrInputDevice.isValid;

     // Add listeners for devices being connected/disconected
     InputDevices.deviceConnected += (device) =>
     {
          if (xrInputDevice == device)
               connectedDevices++;
     }
     InputDevices.deviceDisconnected += (device) =>
     {
          if (xrInputDevice == device)
               connectedDevices--;
     }
}

/* If you want to set "isControllerConnected" if ANY device matches the XRNode:: */
List<InputDevice> xrInputDevices;
int connectedDevices; // Keeps track of the current number
bool isControllerConnected { get => connectedDevices > 0; } // returns true if at least one device is active.
void Start()
{
     // Get target devices
     xrInputDevices = new List<InputDevice>();
     InputDevices.GetDevicesAtXRNode(XRNode.RightHand, xrInputDevices);

     // Initialize the number of connected devices
     connectedDevices = 0;
     foreach (InputDevice device in xrInputDevices)
          if (device.isValid == true)
               connectedDevices++;

     // Add listeners for devices being connected/disconected
     InputDevices.deviceConnected += (device) =>
     {
          // xrInputDevices is fixed at the time of starting this component. Consider adding devices to the list when they are connected and match the XRNode.
          if (xrInputDevices.Contains(device))
               connectedDevices++;
     }
     InputDevices.deviceDisconnected += (device) =>
     {
          if (xrInputDevices.Contains(device))
               connectedDevices--;
     }
}
2 Likes

This is exactly what I was looking for. Thank you!

1 Like