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

how to check if gamepad is still connected?

Discussion in 'Input System' started by ch4vy, Jun 9, 2022.

  1. ch4vy

    ch4vy

    Joined:
    Jan 16, 2022
    Posts:
    5
    i start rumbling, and want to stop after x seconds. the issue is, that the gamepad could have been disconnected in the meantime. how do i check if the gamepad is still connected, before i call gamepad.ResetHaptics()?

    this is what i was doing, but the gamepad is never null:

    Code (CSharp):
    1. Gamepad gamepad = Gamepad.current;
    2. gamepad.SetMotorSpeeds(lowFrequency, highFrequency);
    3. yield return new WaitForSeconds(time);
    4. if (gamepad == null) {// this never triggers
    5.     Debug.Log("gamepad not connected");
    6.     yield break;
    7. }
    8. gamepad.ResetHaptics();
    9.  
    now im simply caching the gamepad.deviceId when i start rumbling, and later when i want to stop, i iterate through the list of available gamepads, to see if the gamepad is still connected. but surely there has to be a more efficient way?
     
    Last edited: Jun 14, 2022
  2. coatline

    coatline

    Joined:
    Jul 31, 2019
    Posts:
    17
    Well, I did a small test.
    When I disconnected my Xbox controller, Gamepad.current read null. I only had this single controller connected.

    My thought is that if you have more than one gamepad connected, then Gamepad.current is going to be one the next gamepad that was connected.

    Here is an example of my understanding of what Gamepad.current returns:
    Gamepad 1
    Gamepad 2
    Gamepad 3

    Gamepad.current = Gamepad 1

    *Disconnect Gamepad 1*

    null
    Gamepad 2
    Gamepad 3

    Gamepad.current = Gamepad 2 instead of null

    But all of this is irrelevant if you only had one Gamepad connected.
    The only other thing that I can think of that may help is Gamepad.current.enabled.
     
    Nefju likes this.
  3. ch4vy

    ch4vy

    Joined:
    Jan 16, 2022
    Posts:
    5
    hi, and thanks for your reply.

    my problem isnt Gamepad.current, but wanting to know if a cached gamepad is still connected. for example, if i start rumbling on Gamepad 1, and the user switches to Gamepad 2 in the meantime, Gamepad 1 will continue to rumble. so i want to know if Gamepad 1 is still connected, before i call gamepad.ResetHaptics().

    even after i disconnected Gamepad 1, gamepad.enabled keeps returning true. i cant expect the user to only have one gamepad, and not wanting to switch between gamepads while playing. so i want to make sure that the transition happens appropriately. (stopping rumbling on Gamepad 1, and transferring the remaining duration to Gamepad 2)

    iterating through the list of gamepads, and comparing the deviceId, works as expected, but there has to be a better way.
     
    Last edited: Jun 10, 2022
  4. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    699
  5. ch4vy

    ch4vy

    Joined:
    Jan 16, 2022
    Posts:
    5
    yes, i was just thinking about that yesterday. i also found out that gamepad.added might do exactly what i need. i will try both, and see which one works better. thanks.
     
  6. Ed-Den-Gaming

    Ed-Den-Gaming

    Joined:
    May 26, 2020
    Posts:
    9
    Hi

    I've used:

    InputSystem.onDeviceChange +=
    (device, change) =>
    {
    switch (change)
    {
    case InputDeviceChange.Added:
    Debug.Log("New device added: " + device);
    break;

    case InputDeviceChange.Removed:
    Debug.Log("Device removed: " + device);
    break;
    }
    };

    and it works perfectly. However, I put it in my Update() function which doesn't seem, the best place for it. Where else should I put it?
     
    reza_b_mirzaei likes this.
  7. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    699
    You can put it either in Start() or if you plan to disable this script in OnEnable() and remove in OnDisable().
     
    Ed-Den-Gaming likes this.
  8. Ed-Den-Gaming

    Ed-Den-Gaming

    Joined:
    May 26, 2020
    Posts:
    9
    Thanks, but:
    This is only called once, at the start. What if a player inserts their device midway through play? How or where do you call this then?
     
  9. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    699
    No it should be called everytime the device changes. In Start you just initialize the callback. If you want more control you can try onActionChange instead. Put a debug message and sees how it goes. If you add a callback repeatedly in Update() it will be called a billion times.
     
    Ed-Den-Gaming likes this.
  10. Ed-Den-Gaming

    Ed-Den-Gaming

    Joined:
    May 26, 2020
    Posts:
    9
    Hey

    Perfect.
    Thanks
     
  11. Ed-Den-Gaming

    Ed-Den-Gaming

    Joined:
    May 26, 2020
    Posts:
    9
    Would you know how to check which device you are currently using onStart? So, I want the display to say z,x,c if there is no gamepad onStart (e.i. keyboard), but, if there is a gamepad, to read x,y,b.

    I tried this:

    //var gamepad = Gamepad.current;
    //if (Gamepad.current.enabled)
    /*
    if (Keyboard.current.enabled)
    {
    fixedInputName.inputButtonName = keyboardName.inputButtonName;
    }
    else
    {
    fixedInputName.inputButtonName = controllerName.inputButtonName;
    }
    */

    but no avail.
     
  12. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    699
    You can get a list of devices but you don't know which one the user is holding. For that you need to use onActionChange like so:

    Code (csharp):
    1.  
    2.             InputSystem.onActionChange += (obj, change) => {
    3.                 if (change == InputActionChange.ActionPerformed)
    4.                 {
    5.                     var action = obj as InputAction;
    6.                     if (action.name != "Navigate")
    7.                     {
    8.                         lastDevice = (obj as InputAction).activeControl.device;
    9.                         updateDeviceType();
    10.                     }
    11.                 }
    12.             };
    13.  
    I don't remember why exactly I filtered Navigate, I think that there are too many of these.
     
  13. Ed-Den-Gaming

    Ed-Den-Gaming

    Joined:
    May 26, 2020
    Posts:
    9

    the lastDevice and updateDeviceType(); throw errors for me. I suppose updateDeviceType(); is a method but I'm unsure how to structure it. Help would be great.
     
  14. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    699
    lastDevice is of type InputDevice, as for the updateDeviceType method, it depends on your needs.

    Code (csharp):
    1.  
    2.         private InputDevice lastDevice;
    3.  
    4.         private void updateDeviceType()
    5.         {
    6.             if (lastDevice is Keyboard)
    7.             {
    8.                 // I have a keyboard
    9.             }
    10.             else if (lastDevice is Mouse)
    11.             {
    12.                 // I have a Mouse
    13.             }
    14.             else if (lastDevice is Gamepad)
    15.             {
    16.                 // I have a gamepad
    17.             }
    18.             else if (lastDevice is Touchscreen)
    19.             {
    20.                 // I have a touchscreen
    21.             }
    22.             else if (lastDevice is Joystick)
    23.             {
    24.                 // I have a joystick
    25.             }
    26.             else
    27.             {
    28.                 // I have an unknown device type
    29.             }
    30.         }
    31.  
     
  15. Ed-Den-Gaming

    Ed-Den-Gaming

    Joined:
    May 26, 2020
    Posts:
    9
    Hello!

    My code still won't recognise that the gamepad is already plugged in when starting. It will allow me to switch between keyboard and gamepad once running but not when pressing Play. This is my code:

    private void Start()
    {
    fixedInputName.inputButtonName = keyboardName.inputButtonName;
    usersButtonRef.text = fixedInputName.inputButtonName;

    CheckCurrentDevice();
    OnDeviceChangedTom();//Works
    }

    private InputDevice lastDevice;
    public void CheckCurrentDevice()
    {
    InputSystem.onActionChange += (obj, change) => {
    if (change == InputActionChange.ActionPerformed)
    {
    var action = obj as InputAction;
    if (action.name != "Navigate")
    {
    lastDevice = (obj as InputAction).activeControl.device;
    updateDeviceType();
    Debug.Log("DEVICE: " + lastDevice);

    }
    }
    };
    }

    private void updateDeviceType()
    {
    if (lastDevice is Gamepad)
    {
    // I have a gamepad
    fixedInputName.inputButtonName = controllerName.inputButtonName;
    usersButtonRef.text = fixedInputName.inputButtonName;
    Debug.Log("DEVICE Gamepad");
    }
    else
    {
    // I have a keyboard
    fixedInputName.inputButtonName = keyboardName.inputButtonName;
    usersButtonRef.text = fixedInputName.inputButtonName;
    Debug.Log("DEVICE Keyboard");
    }
    }

    private string caseCurrent = "something";
    public void OnDeviceChangedTom()
    {
    InputSystem.onDeviceChange +=
    (device, change) =>
    {
    switch (change)
    {
    case InputDeviceChange.Added:
    // New Device.
    fixedInputName.inputButtonName = controllerName.inputButtonName;
    caseCurrent = "InputDeviceChange.Added";
    break;

    case InputDeviceChange.Disconnected:
    // Device got unplugged.
    fixedInputName.inputButtonName = keyboardName.inputButtonName;
    caseCurrent = "InputDeviceChange.Disconnected:";
    break;

    case InputDeviceChange.Reconnected:
    // Plugged back in.
    fixedInputName.inputButtonName = controllerName.inputButtonName;
    caseCurrent = "InputDeviceChange.Reconnected:";
    break;

    case InputDeviceChange.Removed:
    // Remove from Input System entirely; by default, Devices stay in the system once discovered.
    fixedInputName.inputButtonName = keyboardName.inputButtonName;
    caseCurrent = "InputDeviceChange.Removed:";
    break;

    default:
    // See InputDeviceChange reference for other event types.
    //fixedInputName.inputButtonName = keyboardName.inputButtonName;
    break;
    }
    usersButtonRef.text = fixedInputName.inputButtonName;

    Debug.Log("Current Case is: " + caseCurrent);
    };
    usersButtonRef.text = fixedInputName.inputButtonName;
    }


    EDIT: so, if i start with the gamepad plugged in and move or press a button, the text will change to the right reference (as in reference the gamepad), but if the player is still, the text stays as the original keyboard settings. The same is true is the scene chamges.
     
    Last edited: Jan 21, 2023
  16. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    699
    I am not sure how to do that but you can either support both at same time or ask the user to validate by pressing South button or clicking so that you can detect the correct input device at that time.