InputSystem.onDeviceChange event never fires?

I’m currently trying to build in local multiplayer support for my game. Once the game is running, things work great: I just instantiate my Player prefab as many times as I need and the Input System takes care of things, smartly mapping available devices to player prefab instances (each player prefab instance has it’s own Player Input and Player Controller component).

However I need to subscribe to the onDeviceChange event at the main menu to detect how many players (well, technically how many input devices) are present before the game starts. Here is what I have:

using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.InputSystem.Users;

public class InputManager : MonoBehaviour
{
    public static InputManager instance;

    public InputUser[] Players { get; private set; }

    private void Awake()
    {
        if (instance == null) instance = this;
        else if (instance != this) Destroy(this);
        DontDestroyOnLoad(this);
    }

    private void Start()
    {
        // add our listener to the onDeviceChange event
        InputSystem.onDeviceChange += onInputDeviceChange;
        InputSystem.onEvent += onEvent;
    }

    public void onInputDeviceChange(InputDevice device, InputDeviceChange change)
    {
        Debug.Log("onInputDeviceChange");
        switch (change)
        {
            case InputDeviceChange.Added:
                Debug.Log("Device added: " + device);
                break;
            case InputDeviceChange.Removed:
                Debug.Log("Device removed: " + device);
                break;
            case InputDeviceChange.ConfigurationChanged:
                Debug.Log("Device configuration changed: " + device);
                break;
        }
    }

    public void onEvent(InputEventPtr inputEvent, InputDevice device)
    {
        Debug.Log("onEvent");
    }
}

The problem is that the onDeviceChange event never fires - even when I turn on my Xbox controller after the game has started, or disconnect and reconnect the device. The onEvent fires constantly, so that at least works, but I only put that there to test that subscribing to InputSystem events this way does actually work.

I don’t get why the onDeviceChange event doesn’t fire - can anyone see what I’m doing wrong here?

Haven’t tried using this event myself, but first thing I might try is confirm that the Input System is properly convinced that there has been a change. Just a cheap and inefficent tactic :P…but I’d try logging

InputSystem.devices

and plug in/unplug your controllers and just verify that the system is registering the change on some level.

1 Like

Yahoy, thanks for your input friend - I didn’t realise that onDeviceChange only fires when a new, previously unadded device appears.

By turning my controller off and on, an already added device was appearing so the onDeviceAdded event never fired. By starting the game with the controller unplugged, and then plugging it in, the device added event fired as expected, as does the device removed event.

I ended up just going with the PlayerInputManager to handle a local multiplayer set up and instantiating a UI Controller prefab to allow players to join at the skill selection screen.

Yeah, I got the similar problem. My game uses two types of input device - keyboard&mouse and gamepad.
At the beginning of the game, ControlsChangedEvent was fired normally. But after the new level scene loaded (using additive load), the event wasn’t fired anymore.
The player remains in the root scene, and only level scene will be changed. The player is inactivated while changing scene.

1 Like