Search Unity

Resolved What is the best way to handle a list with gamepad sticks?

Discussion in 'Input System' started by dlorre, Nov 9, 2021.

  1. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    699
    What I want is to browse through a list by using the gamepad leftStick. So, top would lead me to the first element, bottom to the last element, left to the previous element and right to the next element.

    It is not complicated to achieve with the new input system but I have 2 problems:

    1) I often get vertical and horizontal events at the same time
    2) when I press right and release the left event triggers

    For the first issue I have written these 2 functions:

    Code (CSharp):
    1.     public static bool HasLateral(InputAction.CallbackContext context)
    2.     {
    3.         if (context.control.device is Gamepad)
    4.         {
    5.             var gamepad = context.control.device as Gamepad;
    6.             return gamepad.leftStick.left.isPressed || gamepad.leftStick.right.isPressed;
    7.         }
    8.         else
    9.         {
    10.             return false;
    11.         }
    12.     }
    13.     public static bool HasVertical(InputAction.CallbackContext context)
    14.     {
    15.         if (context.control.device is Gamepad)
    16.         {
    17.             var gamepad = context.control.device as Gamepad;
    18.             return gamepad.leftStick.up.isPressed || gamepad.leftStick.down.isPressed;
    19.         }
    20.         else
    21.         {
    22.             return false;
    23.         }
    24.     }
    that I can use like this:

    Code (CSharp):
    1.        public void Forward(InputAction.CallbackContext context)
    2.         {
    3.             if (Globals.HasVertical(context))
    4.             {
    5.                 return;
    6.             }
    7.             ...
    8.         }

    They do work but they don't handle the second issue. So I have imagined another way like so:

    Code (CSharp):
    1. private bool isBrowsing = false;
    2.  
    3. private void browsingCanceled()
    4. {
    5.     isBrowsing= false;
    6. }
    7.  
    8. public void Forward()
    9. {
    10.     if (isBrowsing)
    11.     {
    12.         return;
    13.     }
    14.     isBrowsing= true;
    15. }

    Naturally with:

    Code (CSharp):
    1.          
    2.             controls.Browsing.Forward.started += context => Forward(context);
    3.             controls.Browsing.Forward.canceled += context => browsingCanceled();
    4.  
    The idea is to not consider another event until the active one has canceled.

    So, my question is if there is a better way to achieve this result? I have tried using ReadValue() but I didn't get very far with that. Is there some kind of configuration in the Input System that would let me avoid event collisions without all this code?

    ETA: I was hoping to find something that would be ReadValue() based with for example 0.3 left and 0.5 top so I would go for the stick moving top.
     
    Last edited: Nov 9, 2021
  2. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    699
    I have been able to achieve this result by using this setting:

    upload_2021-11-10_11-54-20.png

    Then it's quite straightfoward:

    Code (CSharp):
    1.    private void stickMove(InputAction.CallbackContext context)
    2.     {
    3.         var value = context.ReadValue<Vector2>();
    4.  
    5.         if (Math.Abs(value.x) > Math.Abs(value.y))
    6.         {
    7.             // horizontal
    8.             if (value.x < 0)
    9.             {
    10.                 moveBackward();
    11.             }
    12.             else
    13.             {
    14.                 moveForward();
    15.             }
    16.         }
    17.         else
    18.         {
    19.             // vertical
    20.             if (value.y < 0)
    21.             {
    22.                 moveLast();
    23.             }
    24.             else
    25.             {
    26.                 moveFirst();
    27.             }
    28.         }
    29.  
    30.     }