Search Unity

How would you handle a GetButtonDown Situaiton with the New Input System?

Discussion in 'Input System' started by WizByteGames, Feb 10, 2019.

  1. WizByteGames

    WizByteGames

    Joined:
    Mar 28, 2013
    Posts:
    70
    Basically I want to know how do you check to see if a button is being held down durring a frame. Instead of just being pressed. I'm not sure how to check for this.
     
    dog_funtom, TP3 and DTK34aubie like this.
  2. WizByteGames

    WizByteGames

    Joined:
    Mar 28, 2013
    Posts:
    70
    I have figured out how to do what I needed done. I didn't realize you could have to actions binded to the same button. So all I had to do was add a binding for pressing a button and another for releasing the same button.
     
    StevenMaDesign likes this.
  3. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    There's some other ways you can go about it.

    If all you're interested in is getting one call on press and one on release, hook into started and cancelled.

    Code (CSharp):
    1. myAction.started += /* button was pressed */;
    2. myAction.cancelled += /* button was released */;
    If you want to continuously be notified for as long as the button is held, check the "Continuous" box on the action and use performed and cancelled.

    Code (CSharp):
    1. myAction.performed += /* button was pressed or is held */;
    2. myAction.cancelled += /* button was released */;
     
  4. Albarnie

    Albarnie

    Joined:
    Oct 24, 2015
    Posts:
    18
    Came across this thread, and this solution doesn't work for me. GetButtonDown would be true if it had been pressed in that frame, and false otherwise, and there's no simple and clean way to do this in the new system. this would work however if Started and cancelled got called when using the 'Press' interaction, but they don't for some reason.
    Performed no longer gets called when you release either so you can't use the
    ctx.ReadValue<float>()
    anymore either.

    Either I am doing something wrong here or this needs to be fixed.
     
  5. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Using "Press" and setting it to "Press and Release", you should see "performed" when the button is pressed and "cancelled" when the button is released. In most cases, though, the explicit "Press" interaction shouldn't be necessary. It gives control over press points and such but even without any interaction on a binding to a button, you should "performed" getting called when the button is pressed and "cancelled" when the button is released. At least that's the expected behavior. If that doesn't happen, there's probably a bug.
     
    dog_funtom likes this.
  6. gyl09

    gyl09

    Joined:
    Jul 21, 2017
    Posts:
    9
    Hi,
    I try to check the phase but in both cases (press/release) it returns "Performed".

    Then in debug mode I saw that the Button Control has the members "wasPressedThisFrame" and "wasReleasedThisFrame", but I have another issue which is that when:

    - "Continuous" is unchecked, the event is not send when holding so the flag "wasPressedThisFrame" is not updated

    - "Continuous" is checked, the behaviour is ... the same, events are only raised on press and release action. Is there a point I missed on continuous feature? Do I need to add another interaction? Hold?

    My action config:
    - 'Continuous" checked/unchecked according to the test case
    - Interaction: Press - Press and Release

    I could update the flag "manually" after a Time.deltaTime delay but it seems not the most efficient way to achieve it.
    Thanks for your help
     
  7. Luminoth

    Luminoth

    Joined:
    Jan 15, 2013
    Posts:
    25
    Hi, I just wanted to jump in on this thread as well with a note that Press and Release is 100% always giving "performed" for both events, making it quite difficult to differentiate between the two events. Looking at the code in Github seems to confirm this behavior:


    Code (CSharp):
    1.  
    2.                 case PressBehavior.PressAndRelease:
    3.                     if (m_WaitingForRelease)
    4.                     {
    5.                         if (!isActuated)
    6.                             context.PerformedAndGoBackToWaiting();
    7.                         // No support for continuous mode.
    8.  
    9.                         m_WaitingForRelease = isActuated;
    10.                     }
    11.                     else if (isActuated)
    12.                     {
    13.                         context.PerformedAndGoBackToWaiting();
    14.                         // No support for continuous mode.
    15.  
    16.                         m_WaitingForRelease = true;
    17.                     }
    18.                     break;
    19.  
    I've also noticed that quick taps seem to give only the press "performed" without the release "performed". Is that intentional, and if so, is there a correct way to resolve it?
     
  8. jeremies_unity

    jeremies_unity

    Joined:
    Oct 16, 2018
    Posts:
    26
    I also can't find a way to trigger a button release. Tried every solution mentionned here.

    EDIT: Finally figured it out. The release is also triggered in .performed, NOT .canceled.
     
    Last edited: Jul 8, 2019
    Sonorpearl likes this.
  9. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,609
    I'm currently trying to integrate the new input system in my project and I also ran into the problem how to implement Input.GetButtonDown() and Input.GetButtonUp() in the new input system.

    I'm able to detect button down/up only, when I subscribe to the started/performed and canceled events of an action. In this case, when I press the button associated to the action, it triggers the following events:
    Code (CSharp):
    1. started (frame:678)
    2. performed (frame:678)
    3. canceled (frame:684)
    "started" and "performed" happen during the same frame. "started" corresponds to "GetButtonDown" and "canceled" to "GetButtonUp" I would say. That's what I expected.

    However, I would like to poll the state, rather than subscribing to different events. So I was just dumping the phase of an action to see how it changes as I press and release a button (left ctrl key):
    Code (CSharp):
    1. var fire = m_Controls.Player.Fire;
    2. Debug.LogFormat("phase: {0}, triggered: {1}, value: {2}", fire.phase, fire.triggered, fire.ReadValue<float>());
    But phase never contains performed and canceled. The test outputs:
    Code (CSharp):
    1. phase: Waiting, triggered: False, value: 0 (frame:74)
    2. phase: Started, triggered: True, value: 1 (frame:75)
    3. phase: Started, triggered: False, value: 1 (frame:76) // many of these
    4. ...
    5. phase: Started, triggered: False, value: 1 (frame:93)
    6. phase: Waiting, triggered: False, value: 0 (frame:94)
    7.  
    So how can I poll an action whether it has been "canceled" to emulate Input.GetButtonUp()? With the current phases, it seems I can only emulate GetButtonDown().

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.InputSystem;
    5.  
    6. public class GetButtonDownTest : MonoBehaviour
    7. {
    8.     MyInputControls m_Controls;
    9.  
    10.     void Awake()
    11.     {
    12.         m_Controls = new MyInputControls();
    13.         m_Controls.Enable();
    14.  
    15.         //m_Controls.Player.Fire.started += Fire_started;
    16.         //m_Controls.Player.Fire.performed += Fire_performed;
    17.         //m_Controls.Player.Fire.canceled += Fire_canceled;
    18.     }
    19.  
    20.     void Fire_canceled(InputAction.CallbackContext obj)
    21.     {
    22.         Debug.LogFormat("canceled (frame:{0})", Time.frameCount);
    23.     }
    24.  
    25.     void Fire_performed(InputAction.CallbackContext obj)
    26.     {
    27.         Debug.LogFormat("performed (frame:{0})", Time.frameCount);
    28.     }
    29.  
    30.     void Fire_started(InputAction.CallbackContext obj)
    31.     {
    32.         Debug.LogFormat("started (frame:{0})", Time.frameCount);
    33.     }
    34.  
    35.     void Update()
    36.     {
    37.         var fire = m_Controls.Player.Fire;
    38.         Debug.LogFormat("phase: {0}, triggered: {1}, value: {2} (frame:{3})", fire.phase, fire.triggered, fire.ReadValue<float>(), Time.frameCount);
    39.     }
    40. }
    41.  

    I'm using the preview-1.0.0 package and Unity 2019.3.0b4.
     
    Last edited: Sep 30, 2019
  10. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    @Peter77 Polling an action like that will indeed not observe performed or canceled. The reason is that these simply happen instantaneously and the action then immediately goes back to waiting. I.e. event comes in, action performs, calls its callback, then goes back to waiting. All this happens in the input update and by the time the Update/FixedUpdate code runs, it's history.

    There is no equivalent for polling for an action a la GetButtonUp. GetButtonDown corresponds to InputAction.triggered.

    To observe both press and release requires using callbacks.

    Code (CSharp):
    1. private void bool m_Pressed;
    2. private void bool m_Released;
    3.  
    4. protected void OnEnable()
    5. {
    6.     m_Controls.Player.Fire.performed += ctx => m_Pressed = true;
    7.     m_Controls.Player.Fire.canceled += ctx => m_Released = true;
    8. }
    9.  
    10. protected void Update()
    11. {
    12.     if (m_Pressed)
    13.         /* button down */;
    14.     if (m_Released)
    15.         /* button released */;
    16.  
    17.     m_Pressed = false;
    18.     m_Released = false;
    19. }
    20.  
     
  11. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,609
    Thanks for the reply.

    Is there a way to attach some sort of "Component" to an Action?

    My preferred way to implement these callbacks would be to put the code in a Component and expose hold, pressed, released properties. So I have this code in a single place only. The game code would then get that "action component" to read the state, rather than having to implement the same "subscribe to callback, capture state in three fields, etc" over and over again across the code base?

    I've looked at Interactions and Processors if I could abuse them for my purpose, but I can't see how I would iterate over the Interactions or Processors list. Action.interactions just returns a string, rather than a collection of Interactions.
     
  12. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Not 100% sure what you're looking for but could be that the interface generated as part of the C# class is coming close. E.g. if you have a MyGameActions.inputactions file and have "Generate C# Class" on, there's an interface generated as part of it which you can implement on components.

    Code (CSharp):
    1. public class MyComponent : IMyGameActions
    2. {
    3.     public void OnFire(InputAction.CallbackContext context)
    4.     {
    5.         if (context.performed)
    6.             /* pressed */;
    7.         else if (context.canceled)
    8.             /* released */;
    9.     }
    10. }
    11.  
    The generated SetCallbacks method can be used to automatically hook in the callbacks from an implementation of the interface.
     
  13. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,609
    I was looking for a way to attach custom data and logic to an InputAction. Like attaching a custom Processor to an InputAction.

    My hope was I could implement the callback handling in a single place only, something like a "MonoBehaviour" for InputAction's, which I could then attach to an InputAction through the Input Editor, like it's possible with Processors and Interactions.

    I'll find another way to avoid having to write the same callback handling code for a gazillion InputAction's.

    Thanks again for the help.
     
  14. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    You can alternatively listen to InputActionMap.actionTriggered or even InputSystem.onActionChange. These route callbacks from several actions into one funnel.
     
    Drominus likes this.
  15. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,609
    Yep, these make the code a little less verbose. Thanks!

    Here is what I came up with. I'm surprised how much code is involved for something that seemed to simple initially. Is this how you imagine the system should be used if GetButton/Down/Up-like methods are needed?

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.InputSystem;
    5.  
    6. public class GetButtonDownTest : MonoBehaviour
    7. {
    8.     MyInputControls m_Controls;
    9.     List<ActionState> m_States = new List<ActionState>();
    10.  
    11.  
    12.     class ActionState
    13.     {
    14.         public InputAction action;
    15.         public int downFrame;
    16.         public bool hold;
    17.         public int upFrame;
    18.         public InputAction.CallbackContext context;
    19.  
    20.         public bool down
    21.         {
    22.             get
    23.             {
    24.                 return downFrame == Time.frameCount;
    25.             }
    26.         }
    27.  
    28.         public bool up
    29.         {
    30.             get
    31.             {
    32.                 return upFrame == Time.frameCount;
    33.             }
    34.         }
    35.     }
    36.  
    37.  
    38.     void Awake()
    39.     {
    40.         m_Controls = new MyInputControls();
    41.         m_Controls.Enable();
    42.     }
    43.     void OnEnable()
    44.     {
    45.         m_Controls.Player.Get().actionTriggered += OnActionTriggered;
    46.     }
    47.  
    48.     void OnDisable()
    49.     {
    50.         m_Controls.Player.Get().actionTriggered -= OnActionTriggered;
    51.     }
    52.  
    53.     void Update()
    54.     {
    55.         var fire = m_Controls.Player.Fire;
    56.         if (GetButtonDown(fire))
    57.             Debug.LogFormat("down (frame:{0})", Time.frameCount);
    58.  
    59.         if (GetButtonUp(fire))
    60.             Debug.LogFormat("up (frame:{0})", Time.frameCount);
    61.  
    62.         //Debug.LogFormat("hold: {0}, down: {1}, up: {2} (frame:{3})",
    63.         //    GetButton(fire),
    64.         //    GetButtonDown(fire),
    65.         //    GetButtonUp(fire),
    66.         //    Time.frameCount);
    67.     }
    68.  
    69.     ActionState FindOrCreateState(InputAction action)
    70.     {
    71.         for (var n = 0; n < m_States.Count; ++n)
    72.         {
    73.             if (m_States[n].action == action)
    74.                 return m_States[n];
    75.         }
    76.  
    77.         var entry = new ActionState();
    78.         entry.action = action;
    79.         m_States.Add(entry);
    80.  
    81.         return entry;
    82.     }
    83.  
    84.     void OnActionTriggered(InputAction.CallbackContext obj)
    85.     {
    86.         var state = FindOrCreateState(obj.action);
    87.         state.context = obj;
    88.  
    89.         if (obj.started)
    90.         {
    91.             state.hold = true;
    92.             state.downFrame = obj.duration == 0.0f ? Time.frameCount : -1;
    93.         }
    94.  
    95.         if (obj.canceled)
    96.         {
    97.             state.hold = false;
    98.             state.upFrame = Time.frameCount;
    99.         }
    100.     }
    101.  
    102.     bool GetButton(InputAction action)
    103.     {
    104.         if (action == null)
    105.             return false;
    106.  
    107.         var state = FindOrCreateState(action);
    108.         return state.hold;
    109.     }
    110.  
    111.     bool GetButtonDown(InputAction action)
    112.     {
    113.         if (action == null)
    114.             return false;
    115.  
    116.         var state = FindOrCreateState(action);
    117.         return state.down;
    118.     }
    119.  
    120.     bool GetButtonUp(InputAction action)
    121.     {
    122.         if (action == null)
    123.             return false;
    124.  
    125.         var state = FindOrCreateState(action);
    126.         return state.up;
    127.     }
    128. }
    129.  
     
    Drominus and Tom-Atom like this.
  16. KingRecycle

    KingRecycle

    Joined:
    Jul 20, 2013
    Posts:
    26
    Sadly context.performed isn't called continuously here. How can I use the generated interface and have a "OnLeftMouseButtonHeld" or "GetMouseButton(0)" functionality.
     
  17. Jichaels

    Jichaels

    Joined:
    Dec 27, 2018
    Posts:
    237
    Use the Press and Release interaction, set a flag to true when you get press, then false on release, and use it accordingly
     
    KingRecycle likes this.
  18. miron83

    miron83

    Joined:
    Oct 28, 2015
    Posts:
    6
    Hey, probably a lot of you wonder how to do bind press and release LMB with the new Unity Input System, and well none of sugestions here seems to work...
    I recommend to read this article first: https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/Interactions.html
    There you'll find how interactions on buttons work, and what values you get from specific input types 'ReadValues<>()'

    First of all - performed and canceled works only with "Hold" interaction - canceled is called if we press, hold and release the button before the "Press Point" value (in secounds). If we releas the button after that time, "canceled" won't trigger any action.
    The best way is to choose "Press" Interaction and choose "Press and Release" Trigger Behavior:




    Then, when we press and release, the "performed" function is called for each of the actions (for press and for release), and we also get the float value from the context, if we bind the button to it.
    So:
    Code (CSharp):
    1.  
    2. private Controls controls = null;
    3. private bool LMB;
    4.  
    5. private void Awake() {
    6.    controls.Player.Interact.performed += ctx => ClickAction(ctx.ReadValue<float>());
    7. }
    8. private void OnEnable() => controls.Player.Enable();
    9. private void OnDisable() => controls.Player.Disable();
    10.  
    11. void ClickAction(float b) {
    12.  
    13.    if(b > 0)
    14.       LMB = true;
    15.    else
    16.       LMB = false;
    17. }
    you can also convert float to bool, becausein every programming language 0 = false and any other number = true:

    Code (CSharp):
    1.  
    2. void ClickAction(float b) {
    3.  
    4.    LMB = System.Convert.ToBoolean(b);
    5. }
    or not even retrive the float value, because "performed" calls the action when you click and another time when you release, so in the function you just need to invert the LMB boolion, like this:


    Code (CSharp):
    1.  
    2.  
    3. private bool LMB = false;
    4. private void Awake() {
    5.    controls.Player.Interact.performed += ctx => ClickAction();
    6. }
    7. void ClickAction() {    
    8.       LMB = !LMB;
    9.  
    10. }
     
    Last edited: Jan 17, 2020
  19. StamesGames

    StamesGames

    Joined:
    Sep 4, 2018
    Posts:
    2

    Hi,
    I can't find this continous checkbox that you where talking about. I want an event to trigger every frame a specific button is held down.
    It would be verry nice if you could explain where to find it :)
     
    bas-interactive likes this.
  20. nickleplated

    nickleplated

    Joined:
    Nov 2, 2018
    Posts:
    26
    schkorpio likes this.
  21. StamesGames

    StamesGames

    Joined:
    Sep 4, 2018
    Posts:
    2
    schkorpio likes this.
  22. Chefty

    Chefty

    Joined:
    Jun 17, 2015
    Posts:
    43
    None of the options above worked for me...
    performed is triggered twice: on press AND release. Anybody finally found a real solution ? Or should I just go back to old unity input system ?
     
  23. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    NotaNaN and Chefty like this.
  24. Xquality

    Xquality

    Joined:
    Oct 3, 2018
    Posts:
    2
    If you want to check for input every frame, then create a bool and call this function in Update()

    Just remember to setup the actions as a new actions and enable it. Call this from awake

    public static PlayerInput controls;

    Code (CSharp):
    1.     void SetUpActions()
    2.     {
    3.         controls = new PlayerInput();
    4.         controls.Enable();
    5.     }
    Code (CSharp):
    1. Fire1 = Mathf.Abs(controls.Gameplay.Fire1.ReadValue<float>()) > 0;
    Just set up an action in the inputactions thingy, give it a name, set a keybind to it and then call the above line. It will only return a positive value (hence the math abs). If it's above 0, then your boolean will become true.

    Now you can easily check from another script if this bool is true or false, and do whatever you want with that.

    If you want to do the same for vertical and horizontal (old input style) then do this:

    Code (CSharp):
    1. Vertical = controls.Gameplay.Movement.ReadValue<Vector2>().y;
    2.             Horizontal = controls.Gameplay.Movement.ReadValue<Vector2>().x;
    Hope that helps!
     
  25. JalalGurbanov

    JalalGurbanov

    Joined:
    Sep 30, 2017
    Posts:
    16
    Hi.

    I know I am too late for the party but I was looking to solve the exact problem. I made a little workaround so maybe someone will benefit from it. (By the way, I use Unity Events for pooling)
    Code (CSharp):
    1. private bool interact;
    2.  
    3. public void UpdateInteract(InputAction.CallbackContext context)
    4.     {
    5.        
    6.         if (context.started)
    7.         {
    8.             interact = true;
    9.         }else if (context.canceled)
    10.         {
    11.             interact = false;
    12.         }
    13.  
    14.     }
    15.  
    16. public bool GetInteract()
    17.     {
    18.         //return interact;
    19.  
    20.  
    21.  
    22.         var temp = interact;
    23.         interact = false;
    24.         return temp;
    25.  
    26.     }
     
    msgulberk and Mbastias like this.
  26. Sangemdoko

    Sangemdoko

    Joined:
    Dec 15, 2013
    Posts:
    221
    The code by @JalalGurbanov won't work for subsequent calls if you call the GetInteract function more than once in one frame.

    If you are constrained to use the input in an Update/Tick function, instead of using events, because you need to support legacy content or whatever, I would recommend using .isTriggerd.

    Code (CSharp):
    1. m_InputActions.PlayerControls.DPad.performed += ctx => { m_DPadInput = ctx.ReadValue<Vector2>(); };
    2.  
    3. public void Tick()
    4.         {
    5.             if (m_InputActions.PlayerControls.DPad.triggered == false) {
    6.                 m_DPadInput = Vector2.zero;
    7.             }
    8.         }
    In the example above Tick is called in an Update function.

    If you are using a Monobehavior you could use LateUpdate() to reset the input.

    I hope that helps someone and if you have a better solution please let me know.
     
    JalalGurbanov likes this.
  27. Fressno

    Fressno

    Joined:
    Mar 31, 2015
    Posts:
    185
    for starters, this is superconfusing for a amatuer coder. the old input system was way easier to code. now im lost on a simple way to make a weapon build up its power, and release it when the player wants to fire.
    pages of script needs to be filled for that to work. if i can understand what you guys are saying.
    it was just getKeyDown / getKeyUp before. with a few extra lines for the function.
    This isnt a good way to make it better.
    Versatile yes, but superconfusing.
     
    zeropointblack, Zuchis and 4-bit like this.
  28. Well if you spent the time you spent here posting about the complexities of the new system on reading the manual, you probably would have came across with this page on it:
    https://docs.unity3d.com/Packages/c...csunity3dcomscriptreferenceinputgetbuttonhtml
     
  29. Fressno

    Fressno

    Joined:
    Mar 31, 2015
    Posts:
    185
  30. Fressno

    Fressno

    Joined:
    Mar 31, 2015
    Posts:
    185
    Ive read it, but have no idea to implement it into code.
    I know how to press and hold to get a float value for the buildup. but no idea how to get the release function.
    thanx anyway
     
    4-bit likes this.
  31. mz00956

    mz00956

    Joined:
    Jun 29, 2019
    Posts:
    21
    I found an really easy solution by accident Unbenannt.PNG Unbenannt1.PNG
    I just use ScriptName.ActionMapsName.ActionsName. triggered inside an if. It works with Press Only, Release Only and Press & Release.
    Unbenannt2.PNG
     
    4-bit likes this.
  32. TheOnlyCool1

    TheOnlyCool1

    Joined:
    Sep 10, 2020
    Posts:
    1
    I made a really simple solution that I just felt like sharing even if it's pretty bad. Just have the input set to Press and Release.

    Code (CSharp):
    1. private bool buttonDown = false;
    2.  
    3. private void OnFire()
    4. {
    5.     buttonDown = !buttonDown
    6. }
    So, just check the variable for the button down. I'm not really sure if there are any flaws with this solution, but I just started learning Unity a few days ago. ¯\_(ツ)_/¯
     
  33. viatech

    viatech

    Joined:
    Dec 6, 2017
    Posts:
    56
    Very very late to the party I know but I was here looking for an answer to something else and I noticed this well read post on a topic which seems to have been around since the the new input system was unveiled. So I just thought I'd add my solution to the "Actions as Buttons" idea.

    I have a simple wrapper around an InputAction which provides 3 properties similar to the GetButton calls on the old system. These are IsActionTriggered, IsActionOngoing, IsActionEnded.

    There is also an InputManager class which uses the InputActionWrapper and exposes the actions as named properties. So you can write code in your Update/FixedUpdate loop without having to use text strings like
    Code (CSharp):
    1.  
    2. if (inputManager.Jump.IsActionTriggered)
    3. {
    4. }
    5.  
    6. if (inputManager.Dash.IsActionEnded)
    7. {
    8. }
    9.  
    10. var mov = inputManager.Movement.ReadValue<Vector2();
    11.  
    12.  

    You can still get at all the action functionality such as subscribe to events by using
    Code (CSharp):
    1. inputManager.Fire.Action.started += FireAction_started;
    2.  
    I've attached a super simple small package which shows how to wire it all up to the PlayerInput component which the input system ships with. There's also a QuantizeProcessor in there which makes Gamepad joysticks work like WASD on keyboards.

    Hope it helps
    Cheers
    Mark
     

    Attached Files:

  34. GregoryFenn

    GregoryFenn

    Joined:
    Feb 13, 2018
    Posts:
    43
    Where is the "Continuous" box?
     
  35. nahrens

    nahrens

    Joined:
    Mar 12, 2020
    Posts:
    1
    Didn't quite find the answer I was looking for here, and since this thread is a #1 hit on Bing, I'll add my solution.

    Goal was to:
    1. Use the new Input System
    2. Use the Send Messages behavior in the provided Player Input script
    3. Handle the Send Messages event on button down or button up (one call on new press or release)
    4. Know whether the button was pressed down or released.

    Solution for me was:
    1. Add the button to Master Input, with the option to trigger on press and release:
    masterinput.png

    2. Add Unity's Player Input component to my player object, with the desired behavior set up to Send Messages as shown:
    PlayerInput.png

    3. Create a custom script (PlayerInputShip.cs) as seen above, and capture the messages.
    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3. using UnityEngine.InputSystem;
    4.  
    5. public class PlayerInputShip : MonoBehaviour
    6. {  
    7.     private MasterInput actions;
    8.  
    9.     private void Start()
    10.     {
    11.         PlayerInput input = this.GetComponent<PlayerInput>();
    12.         input.currentActionMap.Enable();
    13.     }
    14.  
    15.     ...
    16.  
    17.     public void OnShootSecondary(InputValue inputValue)
    18.     {
    19.         if (inputValue.isPressed)
    20.             FireSuperGalacticDeathRay();
    21.         else
    22.             StopFirignSuperGalacticDeathRay();
    23.     }
    24. }
    Don't know if this solution is obvious to everyone. Certainly wasn't for me.
     
  36. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Heya, just to add this here as it's relevant to the OP, as of 1.1-preview.2 (released last week) there are now new methods equivalent to GetButton, GetButtonUp, and GetButtonDown. Details in the docs here.

    Code (CSharp):
    1. // GetButton("fire")
    2. playerInput.actions["fire"].IsPressed()
    3.  
    4. // GetButtonDown("fire")
    5. playerInput.actions["fire"].WasPressedThisFrame()
    6.  
    7. // GetButtonUp("fire")
    8. playerInput.actions["fire"].WasReleasedThisFrame()
    This can be used with any action (i.e. not necessary to have it set to Button type). For actions with value types other than float, this goes purely by "magnitude of actuation" which may or may not make sense for your particular case.

    Also, the behavior of Button type actions has been adjusted to properly take press points into account. The behavior of Button type actions without any added interactions is now equivalent to having added a Press interaction before with it set to "Press Only".

    Finally, release thresholds have been added to offset release points slightly from press points. This makes controls such as gamepads a little more stable around the press point.
     
  37. RogueCode

    RogueCode

    Joined:
    Apr 3, 2013
    Posts:
    230
    @Rene-Damm I'm trying to do a really simply thing:

    Code (CSharp):
    1.  
    2.   void Start()
    3.   {
    4.     _inputs = new PlayerInputs();
    5.     _inputs.Enable();
    6.    }
    7.  

    Code (CSharp):
    1.   void Update()
    2.   {
    3.     Debug.Log($"IsFiring: {_inputs.Player.Fire.activeControl.IsPressed()}");
    4.   }
    5.  
    However activeControl is null when fire is not being pressed. What is your intended way of doing this? I can't imagine I'm meant to check if it is null first. Have I missed something?

    p.s. I don't want to use events, I just want to poll.
     
  38. Fenrisul

    Fenrisul

    Joined:
    Jan 2, 2010
    Posts:
    618
    Code (CSharp):
    1. _inputs.Player.Fire.activeControl?.IsPressed()
    ?? o_O Still ugly.
     
  39. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    This is working for me:
    Code (CSharp):
    1. characterActions.Gameplay.Jump.IsPressed()
     
    RogueCode likes this.
  40. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    See @lightbug14's reply.
     
  41. RogueCode

    RogueCode

    Joined:
    Apr 3, 2013
    Posts:
    230
    Awesome, thank you!
     
  42. Lughinu

    Lughinu

    Joined:
    Nov 3, 2016
    Posts:
    11
    InputAction.triggered



    Code (CSharp):
    1.     public bool IsLeftMouseDown()
    2.     {
    3.         return inputActions.UI.Click.triggered;
    4.     }
     
  43. Xavierseal

    Xavierseal

    Joined:
    Oct 31, 2016
    Posts:
    7
    Is there a way to poll the information without generating the C# code for this input action asset?
     
  44. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Yes, if you get the Input action instance then you can use it however you want. For example, getting the action from the asset itself:
    Code (CSharp):
    1. bool pressed = asset.FindAction( actionNameStr ).IsPressed();
     
    Last edited: Dec 11, 2020
    Xavierseal likes this.
  45. Xavierseal

    Xavierseal

    Joined:
    Oct 31, 2016
    Posts:
    7
    Thank you very much. Think I should wait until InputSystem1.1 comes out.
     
    lightbug14 likes this.
  46. Berringer

    Berringer

    Joined:
    Aug 31, 2020
    Posts:
    3
    Been fiddling with this for 3-4 days now, and I give up for now.
    It is the "OnButtonUp" situation that just will not work.

    Only get debugs for:
    Code (CSharp):
    1. if (action.performed) {
    2. Debug.Log("Button Down");
    3. }
    At one point I got both for that and for:
    Code (CSharp):
    1. if (action.canceled) {
    2. Debug.Log("Button Up");
    3. }
    When pressing my jump bindings (Space [Keyboard] & Button South [Gamepad])
    Most of the time while problem solving nothing showed up in console for 'Canceled'

    I'm using both new and old to get what I want atm, and will wait for 1.1 too.
    It works great for my horizontal movement.
    Easier to have this than to fix a custom for d-pad, I think.
     
  47. Elringus

    Elringus

    Joined:
    Oct 3, 2012
    Posts:
    483
    Thank you so much for adding these! Can you please clarify if version 1.1 will eventually become "verified" for a 2019.4 patch release or 1.0 will remain the one "bundled" by default for the current LTS stream?
     
    Xavierseal likes this.
  48. ThatProgrammerJack

    ThatProgrammerJack

    Joined:
    Jan 6, 2019
    Posts:
    32
    This may work in the cases you've described, but what if I wanted to have a bool be false, and then be true just for the frame that the button was pressed, and even if the button is held, the bool returns to false? Basically I want to implement the behavior of
    Code (CSharp):
    1. if (Keyboard.current.spaceKey.wasPressedThisFrame)
    as a Unity event using an InputActions asset so that I don't need to hard-code it for a bunch of different platforms.
     
  49. douglassophies

    douglassophies

    Joined:
    Jun 17, 2012
    Posts:
    141
    This i my issue too. I need to know the difference between a button being pressed on first frame vs it being pressed on every frame thereafter.

    What is the difference between isPressed() and wasPressed()? Or started and performed?
    It seems they run on both the first frame and every frame thereafter until release making them indentical. Only WasReleasedThisFrame() and canceled tell me anything different - the frame of release. Have i done something wrong or is that really how it works?

    I can track each button press and compare it to the last frame myself but it is so much uglier.
     
  50. Krooq

    Krooq

    Joined:
    Jan 30, 2013
    Posts:
    194
    Hi,
    I have found that WasPressedThisFrame() and .triggered seem to "drop" some key presses.
    I'm reading the event in FixedUpdate to perform a jump but it seems that maybe the input system is only guaranteed to read the input values immediately prior to Update as in https://docs.unity3d.com/2021.1/Doc...49.191861334.1614200602-1480888868.1606545039 ??
    Not sure why it would work most of the time but not everytime.

    Maybe this is obvious to everyone but it caused me a lot of grief.
    I ended up using IsPressed()/ReadValue as I was manually applying the isJumping check anyway and this cleared the issue up straight away.