Search Unity

Question How can you get all Gamepad paths via code?

Discussion in 'Input System' started by wbarteck, Jun 23, 2021.

  1. wbarteck

    wbarteck

    Joined:
    Nov 3, 2015
    Posts:
    11
    So big picture; I'm trying to make dictionaries of mappings between gamepad path name to a sprite icon so I can do something like

    PS4 controller mappings ScriptableObject dict
    ButtonSouth : X button.png
    RightBumper: R1 bumper.png
    ...

    Xbox controller mappings ScriptableObject dict
    ButtonSouth : A button.png
    RightShoulder: RB bumper.png
    ...

    And then a monobehaviour can query an input action ref control name to map the action to an on screen prompt based on the playerInput's control scheme/device.

    The main benefit I see for doing it this way instead of assigning an icon to the action ref itself is this can take into account runtime remapping and still show the right button.

    How can I automatically fill out the keys to these dictionaries for the Gamepad layout (doesn't have to be specific to the type of controller, but I don't know, maybe that's easier to do)
     
  2. Check out the In-Game Hints sample in the package manager. Although it only displays a string to hint like "Press Q to pick up" or "Press A to pick up", but you can check how it is doing it and go from there.

    screenshot1.png
     
  3. wbarteck

    wbarteck

    Joined:
    Nov 3, 2015
    Posts:
    11
    Thanks for the reply but its doesn't really answer the question. This sample is just grabbing the display name of the action's keyboard binding and displaying it. That won't really work for me to my knowledge.

    I'm asking about programmatically getting all gamepad binding names, so I can build a dictionary using those as keys.
    The demo just uses
    m_PlayerInput.actions["throw"].GetBindingDisplayString()
    to get the binding of the throw action -- which will work to get the actions current binding, but it wont help me building out a set of mappings for the on-screen icons to use for all possible bindings

    I'm looking for something in the API where I can say something like Gamepad.GetAllBindingPaths and that gets all the keys [buttonSouth, buttonEast, button..... rightShoulder, leftShoulder, etc]
    and then step 2 is using that .GetBindingDisplayString() -> feeding that result into the dictionary to get out a sprite value

    something like this

    Code (CSharp):
    1. Dictionary<string,Sprite> bindingImages;
    2. // which would look like
    3. // buttonNorth : triBtn.png
    4. // buttonSouthb : crossBtn.png
    5. // buttonEast : circleBtn.png
    6. // buttonWest : squareBtn.png
    7. // dpadNorth : dpupBtn.png
    8. // dpadSouth : dpdownBtn.png
    9. // dpadEast : dprightBtn.png
    10. // dpadWest : dpleftBtn.png
    11. // ...
    12. // shoulderRight : r1Btn.png
    13. // shoulderLeft : l1Btn.png
    14. // triggerRight : r2Btn.png
    15. // triggerLeft : l2Btn.png
    16.  
    17. // separate script
    18.  
    19. InputActionRef actionRef;
    20. Image icon;
    21.  
    22. var path = actionRef.action.controls[0].name; //buttonSouth
    23. icon.image = bindingImages.Get(path)
    and I would like to be able to generate all the keys to that dict programmatically instead of by hand
     
    Last edited: Jun 24, 2021
  4. Oh I see what you mean, sorry I misunderstood you previously.

    I don't think it is possible to get all possible bindings from the system.
    But you can get all actively assigned bindings:
    https://docs.unity3d.com/Packages/c...yEngine_InputSystem_InputActionAsset_bindings

    If you make a script, attach your InputActionAsset and iterate through its
    .bindings
    , you can list whatever is assigned there.
    Of course with some manual work you can cheat and assign all possible and potentially used bindings in an InputActionAsset and list that. It can be a lot of work though.

    Or you can open up the package source and parse from there.
    Example:

    [InputControl(name = "buttonSouth", layout = "Button", bit = (uint)GamepadButton.South, usages = new[] { "PrimaryAction", "Submit" }, aliases = new[] { "a", "cross" }, displayName = "Button South", shortDisplayName = ButtonSouthShortDisplayName)]
     
  5. wbarteck

    wbarteck

    Joined:
    Nov 3, 2015
    Posts:
    11
    I like this last idea the most I think, we'll see what I can get out of it. The main goal I want to accomplish with this is to make a system that works even if a player needs to rebind their controls at runtime. So unfortunately just getting all of the current bindings won't cut it if they want to change the "submit" button from buttonSouth to buttonEast, maybe to be more like the nintendo switch. And I also dont want to clutter up the input action asset with a bunch of unused potential bindings.

    Honestly the best thing at this point is probably just doing it manually, it would've been done by now even if its a pain to make. Its not a great solution, and I wish this input system felt a little more complete at times
     
  6. You can have a separate InputActionAsset for all the bindings just for the export. You don't have to put it into your production project at all. :)
    Maybe over the weekend I'll assembly this (it's not a promise! :D).
     
    wbarteck likes this.
  7. If I'm not mistaken this is all of the gamepad bindings:
    Unitypackage also attached.
     

    Attached Files:

    takanaryota likes this.
  8. wbarteck

    wbarteck

    Joined:
    Nov 3, 2015
    Posts:
    11
    That's a good point with the separate input action asset I like that, should make it relatively painless to do. This is very cool thanks for exporting this package!
     
  9. Still will summon @Rene-Damm and/or @dmytro_at_unity maybe they have better idea or they can pick up this as feature request. It's a relatively important point having the possible bindings at hand for either translation or preparing icons for them. Not just the ones we assign by default. And not just for the Gamepad, but for every device.
     
  10. Hookkshot

    Hookkshot

    Joined:
    Jan 11, 2013
    Posts:
    27
    Did this get traction at all internally?
     
  11. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    Huh, this is a bit of necro. Tickled my interest though. I'm sure none of this has changed recently, but this should get you a naïve list of binding paths for any given layout (it will ignore what usage/type it is, fair warning)

    Give this a shot. GetBindingPaths("Gamepad") for example.

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3. using UnityEngine.InputSystem;
    4. using System.Linq;
    5. public static class InputBindingHelpers
    6. {
    7.     // Start is called before the first frame update
    8.    
    9.     public static List<string> GetBindingPaths(string layoutName)
    10.     {
    11.         List<string> bindingPaths = new List<string>();
    12.         RecurseLayout(layoutName, bindingPaths);
    13.         return bindingPaths;
    14.     }
    15.  
    16.     static bool RecurseLayout(string name, List<string> bindingPaths, Stack<string> pathStack = null)
    17.     {
    18.         var layout = InputSystem.LoadLayout(name);
    19.  
    20.         if (pathStack == null)
    21.         {
    22.             pathStack = new Stack<string>();
    23.             if (layout.isGenericTypeOfDevice)
    24.                 pathStack.Push($"<{name}>");
    25.             else
    26.                 pathStack.Push(name);
    27.         }
    28.  
    29.         //has no children, is a binding path
    30.         if (layout.controls.Count == 0)
    31.             return false;
    32.  
    33.         foreach (var c in layout.controls)
    34.         {
    35.             pathStack.Push(c.name);
    36.  
    37.             if (!RecurseLayout(c.layout, bindingPaths, pathStack))
    38.             {
    39.                 bindingPaths.Add(string.Join("/", pathStack.Reverse()));
    40.                 pathStack.Pop();
    41.             }
    42.         }
    43.  
    44.         pathStack.Pop();
    45.  
    46.         return true;
    47.     }
    48. }
    49.  
     
  12. pixel153

    pixel153

    Joined:
    Feb 25, 2018
    Posts:
    1
    Here a few months later but ran into the exact same issue of trying to rebind gamepad inputs at runtime and have those inputs dynamically displayed on screen as prompts. The code uploaded by Fenrisul works perfectly, couldn't have hoped for a more compact solution really. A bit surprising there isn't a way to do this more simply within the Input System and that so few others seam to be trying to do the same thing. Thanks mate you're a legend! Now I've just gotta code the rest of my system :eek:
     
    Fenrisul likes this.
  13. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    This is what the forum is all about heh; we all lift... together.. together...