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

Help to understanding how gamepad connections and disconnects works

Discussion in 'Input System' started by Armetron, Jul 26, 2019.

  1. Armetron

    Armetron

    Joined:
    Oct 7, 2016
    Posts:
    26
    Hello everyone I wanted to ask a few questions that I am hung up on and will hopefully make it easy for anyone searching in the future.

    1) According to the tutorials I've found, once you make an Input system with the Control Scheme, Action Map, and Actions you add the built in Player Input script that will attempt to find an available device that isn't being used by another player input script based on its action map. Is there a way to have a handler assign a specific device to the player inputs manually? If so how?

    2) When the game is running you can see the assigned device in the player input debug window, I have found that if you disconnect the device it will be cleared from the script, however when I reconnect the same device it does not automatically get reassigned to the player input. I have heard mention that the Input System has a way to deal with reconnects but I cant seem to find proper documentation about it. How would I get the device reconnected to the same GameObject or even have a different device of the same type (gamepad) take its spot.

    3) Currently I am working on transferring an old project I made in Gamemaker to Unity, in it I had a character select screen that would detect how many gamepads were connected and would store the selected character and the controllers id number for use in spawning in the next level [0-3] xInput [4-12] dInput. Does the Input system have a way of Identifying or assigning a gamepad with a number?

    Example: (Detects there are 3 xbox controllers and 1 ps4. The xbox are 1, 2, 3 and the ps4 is 4, I unplug xbox 2 and plug in a ps4 gamepad now the new ps4 gamepad is assigned 2.)

    4) And Finally I know that whenever you connect a gamepad unity prompts you that it detected a connection, is there a system event that I can use that fires specifically with gamepads, Kind of like this

    Any help to better understand this new system is greatly appreciated.
     
  2. N163LPH03N1X

    N163LPH03N1X

    Joined:
    Jan 10, 2019
    Posts:
    3
    I'm in the same boat, there's no documentation on this because where it's so new. No one knows other than unity. You'd think there was a input reset method. The old Input manager was much easier to use, only problem was disconnecting and reconnecting a controller, which just added an input value. Say if you were player 2 you would be player 3 because of the re detection array. There was no way to reset it.

    I spent most of the time relearning this new input manager and was told that it was able to handle disconnection, now that I have my game finally reworked to the new system. disconnecting removes the paired controller from say Ex: User #0, in the Debug Input window, reconnecting it does not repair this controller. Although if you code say EX: (Gamepad.current.button.wasPressedThisFrame;) the controller that was disconnected still will run this in the code.

    Any events attached to the player input that was using the specific game pad will cease to function until reboot. Unfortunately using that code above occurs for all game pad devices, there is no specific code to to run for one controller. EX: (Gamepad.User #1.button.wasPressedThisFrame;) otherwise I'd chuck away all of the events for one specific button I've had setup in the Input Actions.
     
  3. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Either spawn PlayerInputs directly like so

    Code (CSharp):
    1. var p1 = PlayerInput.Instantiate(playerPrefab, controlScheme: "abc", device: ...);
    2. var p1 = PlayerInput.Instantiate(playerPrefab, controlScheme: "abc", device: ...);
    Or reassign devices after the fact

    Code (CSharp):
    1. // Unassign devices from all players.
    2. foreach (var player in Player.all)
    3.     player.user.UnpairDevices();
    4.  
    5. // Manually assign specific devices to specific players.
    6. InputUser.PerformPairingWithDevice(..., user: PlayerInput.all[0]);
    7. InputUser.PerformPairingWithDevice(..., user: PlayerInput.all[1]);
    8.  
    9. // Alternatively, use SwitchCurrentControlScheme to switch and
    10. // pair at the same time.
    11. Player.all[0].SwitchCurrentControlScheme("a", deviceA, deviceB);
    12. Player.all[0].SwitchCurrentControlScheme("b", deviceC);
    13.  
    It should be handled automatically but I'm pretty sure we're still looking patchy here in practice. Feel free to send a bug report our way.

    Overall, would recommend taking the players along rather than trying to recreate them and their device pairings. I.e. either make the respective GameObjects DontDestroyOnLoad or put them in a separate scene and use additive loading.

    If you do want to destroy player instances and re-create them, you can persist the list of devices as is. InputDevices will not get destroyed on level loads.

    There's also InputDevice.deviceId which gives numeric IDs to devices but note that a device ID for a specific piece of hardware will change when the device is disconnected and reconnected.

    XInput device user indices are not currently exposed through the API.

    InputSystem.onDeviceChange is probably what you're looking for.
     
    Flow-Hockey and TP3 like this.
  4. AlbertoQUByte

    AlbertoQUByte

    Joined:
    Jun 9, 2020
    Posts:
    4
    This might be a late reply, but I believe this thread is close to what I'm currently having. Whenever I try to reconnect a controller after the main controller that started the game was disconnected (either by disconnecting it from the PS4 console or by the battery running out) I get bombarded with the same error constantly and the inputs stop working.


    Code (CSharp):
    1. 03:35:05    IndexOutOfRangeException: Index was outside the bounds of the array.
    2. 03:35:05      at UnityEngine.InputSystem.Utilities.ArrayHelpers.EraseSliceWithCapacity[TValue] (TValue[]& array, System.Int32& length, System.Int32 index, System.Int32 count) [0
    3. 03:35:05    x00000] in <00000000000000000000000000000000>:0
    4. 03:35:05      at UnityEngine.InputSystem.Users.InputUser.UpdateControlSchemeMatch (System.Int32 userIndex, System.Boolean autoPairMissing) [0x00000] in <000000000000000000000000
    5. 03:35:05    00000000>:0
    6. 03:35:05      at UnityEngine.InputSystem.Users.InputUser.UnpairDevices () [0x00000] in <00000000000000000000000000000000>:0
    7. 03:35:05      at UnityEngine.InputSystem.PlayerInput.OnUnpairedDeviceUsed (UnityEngine.InputSystem.InputControl control, UnityEngine.InputSystem.LowLevel.InputEventPtr eventPtr)
    8. 03:35:05     [0x00000] in <00000000000000000000000000000000>:0
    9. 03:35:05      at UnityEngine.InputSystem.Users.InputUser.OnEvent (UnityEngine.InputSystem.LowLevel.InputEventPtr eventPtr, UnityEngine.InputSystem.InputDevice device) [0x00000]
    10. 03:35:05    in <00000000000000000000000000000000>:0
    11. 03:35:05      at UnityEngine.InputSystem.InputManager.OnUpdate (UnityEngine.InputSystem.LowLevel.InputUpdateType updateType, UnityEngine.InputSystem.LowLevel.InputEventBuffer& e
    12. 03:35:05    ventBuffer) [0x00000] in <00000000000000000000000000000000>:0
    13. 03:35:05      at UnityEngine.InputSystem.LowLevel.NativeInputRuntime+<>c__DisplayClass7_0.<set_onUpdate>b__0 (UnityEngineInternal.Input.NativeInputUpdateType updateType, UnityEn
    14. 03:35:05    gineInternal.Input.NativeInputEventBuffer* eventBufferPtr) [0x00000] in <00000000000000000000000000000000>:0
    15. 03:35:05      at UnityEngineInternal.Input.NativeInputSystem.NotifyUpdate (UnityEngineInternal.Input.NativeInputUpdateType updateType, System.IntPtr eventBuffer) [0x00000] in <0
    16. 03:35:05    0000000000000000000000000000000>:0
    17. 03:35:05    UnityEngine.DebugLogHandler:LogException(Exception, Object)
    18. 03:35:05    UnityEngine.Logger:LogException(Exception, Object)
    19. 03:35:05    UnityEngine.Debug:LogException(Exception)
    20. 03:35:05    UnityEngine.InputSystem.LowLevel.<>c__DisplayClass7_0:<set_onUpdate>b__0(NativeInputUpdateType, NativeInputEventBuffer*)
    21. 03:35:05    UnityEngineInternal.Input.NativeInputSystem:NotifyUpdate(NativeInputUpdateType, IntPtr)
    Quick sidenote, Ive seen that this happens on all platforms and is not exclusive to playstation. This also happens when I enter the main menu, but during the splash screen it functions normally.
     
    Last edited: Sep 29, 2020
  5. AlbertoQUByte

    AlbertoQUByte

    Joined:
    Jun 9, 2020
    Posts:
    4
    On further testing, I've noticed this is also happening in the editor. When I disconnect and reconnect a controller the first time, it functions normally. However, when I disconnect and reconnect again it starts the same error.


    Code (CSharp):
    1. IndexOutOfRangeException: Index was outside the bounds of the array.
    2. (wrapper stelemref) System.Object.virt_stelemref_class_small_idepth(intptr,object)
    3. UnityEngine.InputSystem.Utilities.ArrayHelpers.EraseSliceWithCapacity[TValue] (TValue[]& array, System.Int32& length, System.Int32 index, System.Int32 count) (at Library/PackageCache/com.unity.inputsystem@1.1.0-preview.1/InputSystem/Utilities/ArrayHelpers.cs:740)
    4. UnityEngine.InputSystem.Users.InputUser.UpdateControlSchemeMatch (System.Int32 userIndex, System.Boolean autoPairMissing) (at Library/PackageCache/com.unity.inputsystem@1.1.0-preview.1/InputSystem/Plugins/Users/InputUser.cs:1360)
    5. UnityEngine.InputSystem.Users.InputUser.UnpairDevices () (at Library/PackageCache/com.unity.inputsystem@1.1.0-preview.1/InputSystem/Plugins/Users/InputUser.cs:639)
    6. UnityEngine.InputSystem.PlayerInput.OnUnpairedDeviceUsed (UnityEngine.InputSystem.InputControl control, UnityEngine.InputSystem.LowLevel.InputEventPtr eventPtr) (at Library/PackageCache/com.unity.inputsystem@1.1.0-preview.1/InputSystem/Plugins/PlayerInput/PlayerInput.cs:1836)
    7. UnityEngine.InputSystem.Users.InputUser.OnEvent (UnityEngine.InputSystem.LowLevel.InputEventPtr eventPtr, UnityEngine.InputSystem.InputDevice device) (at Library/PackageCache/com.unity.inputsystem@1.1.0-preview.1/InputSystem/Plugins/Users/InputUser.cs:1735)
    8. UnityEngine.InputSystem.InputManager.OnUpdate (UnityEngine.InputSystem.LowLevel.InputUpdateType updateType, UnityEngine.InputSystem.LowLevel.InputEventBuffer& eventBuffer) (at Library/PackageCache/com.unity.inputsystem@1.1.0-preview.1/InputSystem/InputManager.cs:2693)
    9. UnityEngine.InputSystem.LowLevel.NativeInputRuntime+<>c__DisplayClass7_0.<set_onUpdate>b__0 (UnityEngineInternal.Input.NativeInputUpdateType updateType, UnityEngineInternal.Input.NativeInputEventBuffer* eventBufferPtr) (at Library/PackageCache/com.unity.inputsystem@1.1.0-preview.1/InputSystem/NativeInputRuntime.cs:60)
    10. UnityEngine.InputSystem.LowLevel.<>c__DisplayClass7_0:<set_onUpdate>b__0(NativeInputUpdateType, NativeInputEventBuffer*)
    11. UnityEngineInternal.Input.NativeInputSystem:NotifyUpdate(NativeInputUpdateType, IntPtr)
    I've tried updating to 1.1.0 to see if it there was a fix inside that update, but it doesn't.


    EDIT: I found out that if I disable Auto-Switch from my PlayerInput and set the scheme to be Gamepad straight away, the error disappears, but I lose all the functionality of inputs that are based on PlayerInputs events, while EventSystem based inputs work normally. Maybe I should instantiate a new PlayerInput prefab on reconnection? (it's a single player game)


    EDIT 2: I managed a workaround for now, using a custom script that dispatch the events that the PlayerInput originally invoked, and registering a function call for the events on each .performed of the inputs that each originally used, so I stopped using player inputs entirely.
     
    Last edited: Sep 29, 2020
  6. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,472
    Does this resolved? If xbox controller lost connection to PC(windows) and then reconnect, but unity editor does not recognize it at none-playing status. Why? Only I can do is turn off unity program and turn on again.