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

How to map thumbstick axis to a button action

Discussion in 'Input System' started by Clavus, Feb 8, 2020.

  1. Clavus

    Clavus

    Joined:
    Jun 6, 2014
    Posts:
    61
    I'm trying to map 'pushing the thumbstick up' to a specific action, but I can't quite see how I go about doing this in this system. So basically if "thumbstick y > 0.5" then trigger the action.
     
  2. Clavus

    Clavus

    Joined:
    Jun 6, 2014
    Posts:
    61
    If this isn't supported, please consider this a feature request then.
     
  3. Rene-Damm

    Rene-Damm

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    There's up/down/left/right child controls on each of the sticks which you can bind to.

    upload_2020-2-13_18-14-46.png
     
  4. Clavus

    Clavus

    Joined:
    Jun 6, 2014
    Posts:
    61
    Hm these appear to be available for the gamepad but I'm not seeing them for the thumbstick on the XRController, which is the one I need.
     
  5. Rene-Damm

    Rene-Damm

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    What's the device? Oculus Touch?

    Looking at the code, that one indeed sets up the stick as a simple Vector2Control instead of as a StickControl. Looks wrong. Checking with XR team.
     
  6. Clavus

    Clavus

    Joined:
    Jun 6, 2014
    Posts:
    61
    Indeed the Oculus Touch. Hope this'll get fixed, since tilting the stick forward for teleport is a common action for example.

    When using the input debugger on my Touch controllers I also noticed a few inputs do not seem to be read correctly, so maybe the XR and input team need to do another pass over it.
     
  7. rayant77

    rayant77

    Joined:
    May 27, 2017
    Posts:
    3
    Attempt to resurrect an old thread here... trying to do exactly the same thing as the OP, map controller thumbstick up (Quest 2) to a button action so it can be used for "select action" on the XR toolkit component "XR Controller (Action-Based)" - a pretty standard input scheme for VR teleport. Is this possible in the current input system (1.0.2) ?
     
  8. DanBourque

    DanBourque

    Joined:
    Jul 13, 2013
    Posts:
    3
    I'm eager to hear the solution to this one too. We can get the desired behaviour through code, of course, but it'd be nice to simply set it up in the action maps.
     
  9. slippyfrog

    slippyfrog

    Joined:
    Jan 18, 2016
    Posts:
    42
    Hey, i'm also interested in a solution to this for the Quest. It would be great to be able to map single taps as well as multi-taps of an axis in a particular direction to Actions.
     
  10. Rob-Fireproof

    Rob-Fireproof

    Joined:
    Dec 18, 2012
    Posts:
    55
    Another bump for this! Seems crazy that arbitrary axes can't be mapped as buttons, without controller-specific work being done. (Rewired handles this case flawlessly)
     
  11. dmytro_at_unity

    dmytro_at_unity

    Unity Technologies

    Joined:
    Feb 12, 2021
    Posts:
    212
    Hi folks, would you mind to report a bug for this (help->report a bug)? Thanks!
     
  12. Rob-Fireproof

    Rob-Fireproof

    Joined:
    Dec 18, 2012
    Posts:
    55
  13. Rob-Fireproof

    Rob-Fireproof

    Joined:
    Dec 18, 2012
    Posts:
    55
    BTW if anyone needs a quick hack to get around this, you can make a class derived from InputBindingComposite<float> which has a Vector2 InputControl, and converts the V2 to a float based on a "direction" value. That lets you map a Vector2 input to a Button action.

    Here's my (barely tested) version:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3. using UnityEditor;
    4. using UnityEngine.InputSystem;
    5. using UnityEngine.InputSystem.Layouts;
    6. using UnityEngine.InputSystem.Utilities;
    7.  
    8. public struct Vector2MagnitudeComparer : IComparer<Vector2>
    9. {
    10.     public int Compare(Vector2 x, Vector2 y)
    11.     {
    12.         var lenx = x.sqrMagnitude;
    13.         var leny = y.sqrMagnitude;
    14.  
    15.         if (lenx < leny)
    16.             return -1;
    17.         if (lenx > leny)
    18.             return 1;
    19.         return 0;
    20.     }
    21. }
    22.  
    23. // Use InputBindingComposite<TValue> as a base class for a composite that returns
    24. // values of type TValue.
    25. // NOTE: It is possible to define a composite that returns different kinds of values
    26. //       but doing so requires deriving directly from InputBindingComposite.
    27. #if UNITY_EDITOR
    28. [InitializeOnLoad] // Automatically register in editor.
    29. #endif
    30. // Determine how GetBindingDisplayString() formats the composite by applying
    31. // the  DisplayStringFormat attribute.
    32. [DisplayStringFormat("{firstPart}")]
    33. public class SectorComposite : InputBindingComposite<float>
    34. {
    35.     // Each part binding is represented as a field of type int and annotated with
    36.     // InputControlAttribute. Setting "layout" restricts the controls that
    37.     // are made available for picking in the UI.
    38.     //
    39.     // On creation, the int value is set to an integer identifier for the binding
    40.     // part. This identifier can read values from InputBindingCompositeContext.
    41.     // See ReadValue() below.
    42.     [InputControl(layout = "Vector2")]
    43.     public int VectorControl;
    44.    
    45.     public enum Directions
    46.     {
    47.         North,
    48.         South,
    49.         East,
    50.         West,
    51.     }
    52.  
    53.     public Directions Direction;
    54.  
    55.     // This method computes the resulting input value of the composite based
    56.     // on the input from its part bindings.
    57.     public override float ReadValue(ref InputBindingCompositeContext context)
    58.     {
    59.         return EvaluateMagnitude(ref context);
    60.     }
    61.  
    62.     // This method computes the current actuation of the binding as a whole.
    63.     public override float EvaluateMagnitude(ref InputBindingCompositeContext context)
    64.     {
    65.         // Compute normalized [0..1] magnitude value for current actuation level.
    66.         var vecValue = context.ReadValue<Vector2, Vector2MagnitudeComparer>(VectorControl);
    67.  
    68.         //Find the biggest axis, and only consider that one
    69.         if (Mathf.Abs(vecValue.x) > Mathf.Abs(vecValue.y))
    70.         {
    71.             if (vecValue.x < 0.0f && Direction == Directions.West)
    72.             {
    73.                 return Mathf.Abs(vecValue.x);
    74.             }
    75.             else if (vecValue.x > 0.0f && Direction == Directions.East)
    76.             {
    77.                 return vecValue.x;
    78.             }
    79.         }
    80.         else
    81.         {
    82.             if (vecValue.y < 0.0f && Direction == Directions.South)
    83.             {
    84.                 return Mathf.Abs(vecValue.y);
    85.             }
    86.             else if (vecValue.y > 0.0f && Direction == Directions.North)
    87.             {
    88.                 return vecValue.y;
    89.             }
    90.            
    91.         }
    92.        
    93.         return 0.0f;
    94.     }
    95.  
    96.     static SectorComposite()
    97.     {
    98.         // Can give custom name or use default (type name with "Composite" clipped off).
    99.         // Same composite can be registered multiple times with different names to introduce
    100.         // aliases.
    101.         //
    102.         // NOTE: Registering from the static constructor using InitializeOnLoad and
    103.         //       RuntimeInitializeOnLoadMethod is only one way. You can register the
    104.         //       composite from wherever it works best for you. Note, however, that
    105.         //       the registration has to take place before the composite is first used
    106.         //       in a binding. Also, for the composite to show in the editor, it has
    107.         //       to be registered from code that runs in edit mode.
    108.         InputSystem.RegisterBindingComposite<SectorComposite>();
    109.     }
    110.  
    111.     [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    112.     static void Init() {} // Trigger static constructor.
    113. }
    114.  
     
    nikkelei_unity likes this.
  14. Rob-Fireproof

    Rob-Fireproof

    Joined:
    Dec 18, 2012
    Posts:
    55
  15. dmytro_at_unity

    dmytro_at_unity

    Unity Technologies

    Joined:
    Feb 12, 2021
    Posts:
    212
    Sorry there was some confusion, we reopened it and moved the bug report to our team tracker.
     
    slippyfrog likes this.
  16. Rob-Fireproof

    Rob-Fireproof

    Joined:
    Dec 18, 2012
    Posts:
    55
    Great. Thanks!
     
  17. leeprobert

    leeprobert

    Joined:
    Feb 12, 2015
    Posts:
    40
    Was this fixed?
     
  18. Rob-Fireproof

    Rob-Fireproof

    Joined:
    Dec 18, 2012
    Posts:
    55
    The last I heard is that this is a massive change under the hood, and will be broken down and tackled in a few stages so it might take a while.

    ¯\_(ツ)_/¯
     
  19. FarmerInATechStack

    FarmerInATechStack

    Joined:
    Dec 28, 2020
    Posts:
    54
  20. RisingForceUnity

    RisingForceUnity

    Joined:
    Jan 5, 2023
    Posts:
    36
    I'm trying to recreate the Charging animation from Beat-Em-Ups like Growl where you move by moving your stick (but my game setting are new input system using keyaboard,gamepad,joytsick new input sytem) .
    I was wondering if it was possible to utilize the Double/Multi-Tap or if I press "twice" or double tap or named as you wish ... suing the same Interaction on an Axis "x" rather than a button , use the same axes to move (walking) or (charge or slashing animations) ... using only new input system (Since this needs to work regardless whether you use a keyboard or a joystick and it is easy setup cuase use unity events embeded). I opened a post similar , I would like to make beat em up style using the new input system.
     
  21. ElementalGamer12

    ElementalGamer12

    Joined:
    Apr 17, 2023
    Posts:
    1
    Hey i think they finally added a way to make the thumstick-as to a button action work. So to map the thumbstick axis to a button action in Unity, you'll need to use the Input Manager. Here are the steps you can follow:

    Open the Input Manager by going to "Edit" in the Unity menu and then to "Project Settings" and "Input".

    Under "Axes" you can add a new axis. Give this axis a name relevant to the action you want to perform, for example "Horizontal" for moving left and right.

    Select the new axis and add a positive and negative key. For example: "Joystick Axis X Positive" and "Joystick Axis X Negative" for a horizontal thumbstick axis.

    Then assign the axis to the button action by writing the code. You can do this with an if statement. For example:

    if (Input.GetAxis("Horizontal") > 0)
    {
    // perform action for moving right
    }

    if (Input.GetAxis("Horizontal") < 0)
    {
    // perform action for moving left
    }

    You can repeat the same steps for other thumbstick axis directions or other actions you want to map to buttons.
    Hopefully this helps!
     
  22. RisingForceUnity

    RisingForceUnity

    Joined:
    Jan 5, 2023
    Posts:
    36
    I got it, but how it is work this for new input system based on "callbacks" context where context is the button suscribed to the event ? on the new input system... I am trying to study the Phases of the button , when it is perforemed and started... to try to catch the "stick" arcade simulation with double-tapping using the stick or control of direction (gamepad,joystick,arcadestick , WSAD , arrow's keyboard, etc).