Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Show current button for some Action

Discussion in 'Input System' started by wagenheimer, May 21, 2020.

  1. wagenheimer

    wagenheimer

    Joined:
    Jun 1, 2018
    Posts:
    319
    Hi!

    I have an action Fire, which is Left Mouse Button if player is using Mouse or the X button on XBox Controller.

    I need to show in the UI a Hint to press this button. How to get the current "button description" that should be pressed according to the input method the player is using now?

    Is this possible?
     
  2. wagenheimer

    wagenheimer

    Joined:
    Jun 1, 2018
    Posts:
    319
    I found the answer here : https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/ActionBindings.html

    As simple as :
    Code (csharp):
    1.  
    2.  action.GetBindingDisplayString();
    3.  
    To show images :
    Code (csharp):
    1.  
    2.    // Call GetBindingDisplayString() such that it also returns information about the
    3.    // name of the device layout and path of the control on the device. This information
    4.    // is useful for reliably associating imagery with individual controls.
    5.    var bindingString = action.GetBindingDisplayString(out deviceLayout, out controlPath);
    6.  
    7.    // If it's a gamepad, look up an icon for the control.
    8.    Sprite icon = null;
    9.    if (!string.IsNullOrEmpty(deviceLayout)
    10.        && !string.IsNullOrEmpty(controlPath)
    11.        && InputSystem.IsFirstLayoutBasedOnSecond(deviceLayout, "Gamepad"))
    12.    {
    13.        switch (controlPath)
    14.        {
    15.            case "buttonSouth": icon = aButtonIcon; break;
    16.            case "dpad/up": icon = dpadUpIcon; break;
    17.            //...
    18.        }
    19.    }
    20.  
    21.    // If you have an icon, display it instead of the text.
    22.    var text = m_RebindButton.GetComponentInChildren<Text>();
    23.    var image = m_RebindButton.GetComponentInChildren<Image>();
    24.    if (icon != null)
    25.    {
    26.        // Display icon.
    27.        text.gameObject.SetActive(false);
    28.        image.gameObject.SetActive(true);
    29.        image.sprite = icon;
    30.    }
    31.    else
    32.    {
    33.        // Display text.
    34.        text.gameObject.SetActive(true);
    35.        image.gameObject.SetActive(false);
    36.        text.text = bindingString;
    37.    }
    38.  
     
    Marscaleb and forestrf like this.
  3. Ommageden

    Ommageden

    Joined:
    Sep 24, 2020
    Posts:
    7
    Thanks my dude
     
    wagenheimer likes this.
  4. David_Faulkner

    David_Faulkner

    Joined:
    Oct 5, 2013
    Posts:
    33
    Hi

    I'm probably being dumb here, but I can't get this to work. It seems I'm missing the matching overload method for GetBindingDisplayString(out deviceLayout, out controlPath);.

    The closest I can see is this:
    Code (CSharp):
    1. public static string GetBindingDisplayString(this InputAction action, int bindingIndex, out string deviceLayoutName, out string controlPath, InputBinding.DisplayStringOptions options = 0);
    As this is an example from the documentation I assume there must be a way to make it work.

    The project is in Unity 2019.4.28 and the Input System is version 1.0.2.

    Tested in a new empty project in case it was something wrong with the imported Input System package but had the same problem.

    Has anyone else had this problem?

    Thanks
     
    annerichter likes this.
  5. David_Faulkner

    David_Faulkner

    Joined:
    Oct 5, 2013
    Posts:
    33
    So here's the example from the documentation : https://docs.unity3d.com/Packages/c.../ActionBindings.html#showing-current-bindings

    It shows this as part of an example for displaying bindings as images:

    Code (CSharp):
    1. // Call GetBindingDisplayString() such that it also returns information about the
    2.     // name of the device layout and path of the control on the device. This information
    3.     // is useful for reliably associating imagery with individual controls.
    4.     var bindingString = action.GetBindingDisplayString(out deviceLayout, out controlPath);
    but as far as I can tell, this extension method doesn't exist. Maybe this got removed at some point but this part of the documentation wasn't updated?
     
  6. EMOTION-THEORY

    EMOTION-THEORY

    Joined:
    Jul 16, 2013
    Posts:
    81
    Having the same problem. Indeed it looks like the override was removed.

    I'm pulling my hair out trying to figure out how to get the deviceLayout and controlPath as it is needed for figuring out which icon to use.
     
  7. David_Faulkner

    David_Faulkner

    Joined:
    Oct 5, 2013
    Posts:
    33
    So I think I've got it to work... sort of.

    Code (CSharp):
    1.  
    2. var deviceLayout = default(string);
    3. var controlPath = default(string);
    4.  
    5. InputAction action = m_Action.action;
    6.  
    7. var currentControlScheme = InputUser.all[0].controlScheme;
    8.          
    9. var bindingIndex = action.GetBindingIndex(currentControlScheme.Value.bindingGroup);
    10.  
    11. var bindingString = action.GetBindingDisplayString(bindingIndex, out deviceLayout, out controlPath);
    12.  
    I get the current control scheme from the first user, and use that to get the binding index. I'm not sure how safe it is to assume that the first user will always be the correct one though. I'm making a single player game, so maybe it's okay?

    Anyway, testing in the editor and on a quick dev build to my Android device it seems to be working.
     
    annerichter and EMOTION-THEORY like this.
  8. annerichter

    annerichter

    Joined:
    Apr 29, 2020
    Posts:
    8
    Same. The documentation on the InputSystem is a mess. Its so hard to follow. Everytime you want to do something slightly more advanced, you find nothing. Why is it so hard to have a InputAction.currentActiveBinding ????
     
  9. annerichter

    annerichter

    Joined:
    Apr 29, 2020
    Posts:
    8
    Thank you so so much you are my hero!

    Edit: I found another solution. This one doesnt need to use another library:
    https://forum.unity.com/threads/getting-current-control-path-from-inputaction.1138462/#post-7320547
     
    Last edited: Jul 23, 2021
    David_Faulkner likes this.
  10. tobias_froihofer

    tobias_froihofer

    Joined:
    Jul 30, 2015
    Posts:
    45
    Hi, for anyone who wants to add a similar feature. I created an asset that allows you to display input bindings in TextMeshPro texts side by side with other text. It makes use of the style tag of TMPro to display sprites/text for the current input bindings. There is a manager that subscribes to the "Player Input" component's ControlsChangedEvent and automatically updates the TMPro style sheet and the TMPro texts to display sprites if the player switches to a different device (Keyboard/Mouse or Gamepads).

    All you need to do is type <style=NameOfActionMap/NameOfAction> into a TMPro text field and it will display the current binding(s) for that action.

    The asset also contains prefabs which you can use to rebind the actions of the InputActionAssets.

    I hope it will be useful to some of you: https://assetstore.unity.com/packages/slug/213736
     
    CliffCawley and David_Faulkner like this.