[SOLVED] GetButtonDown / GetButtonUp with the new system

EDIT: Solution :smile: [SOLVED] GetButtonDown / GetButtonUp with the new system - Unity Engine - Unity Discussions

Hello. First of all, congrats for the UI with this new Input System. It’s waaaaay better than the old one. The setup of different button for PC/XBOX/PS4 works perfectly!

However, the new system is also really confusing and i feel that even with all its limitations, the old system was way easier to setup and control.

I have a simple Jump action that requires GetButtonDown and GetButtonUp. Cool, with the old system it was two lines of code.

I tried to do this with the new system for hours and i cannot understand how it really works. It doesn’t help that the tutorials/videos/forums explain things in 2/3 different ways, and the Migrating section of the documentation is really vague in terms of explaining how to setup ButtonUp/Down.

So, i ask for help because i feel totally lost:

This was my previous code

 public bool GetJump(bool Down)
    {
            if (Down)
            {
                return Input.GetButtonDown("Jump");
            }
            else
            {
                return Input.GetButtonUp("Jump");
            }
    }

And yes, i have read dozens of threads before creating this post. And no, none of the ‘solutions’ worked. We just want a simple way to get the two events, because this is the nonsense that i have and still fails:

 private void Awake()
    {
        controls = new PlayerControls();
        controls.Gameplay.Move.performed += ctx => _directionInfo = ctx.ReadValue<Vector2>();
        controls.Gameplay.Jump.started += ctx => _JumpPressed = true; _JumpReleased = false;
        controls.Gameplay.Jump.canceled += ctx => _JumpPressed = false;
}

My Jump button is set to Tap. It’s the closest thing to the previous version of my Jump, but still fails.

In fact, the closest one was this:

controls.Gameplay.Jump.performed -= ctx =>
        {
            var control = ctx.control;
            var button = control as ButtonControl;

            if (button != null)
            {
                if (button.wasPressedThisFrame)
                {
                    _JumpPressed = true;
                    _JumpReleased = false;
                }
                else if (button.wasReleasedThisFrame)
                {
                    _JumpPressed = false;
                    _JumpReleased = true;
                }
            }
        };

Jump button on Press and Release. ALMOST WORKS, but i can hold Jump and i will jump constantly once i touch the ground again. With the old system, ButtonDown will be called one time, and i need to ButtonUp for the next Jump.

Even if i can get this to work, the new system in its current state is way difficult to setup compared to the old one. There are 2/3 ways that i saw on the forums to configure things. It’s modularity is killing the most basic setups for a lot of teams, which will end up using the old one or just purchasing one from the Asset Store.

Just made some tutorials that cover a lot of this using just the new InputSystem! :slight_smile:

Alternatively, having had the exact same pains you did.

I wrote this alternative C# Wrapper Generator that sorts most of it out if you want to give it a look :slight_smile:

Thanks for the help! Sadly, I can’t recreate GetButtonDown

My function sends the actual value of GetButtonDown. So, with the old system, GetButtonDown will be active for a moment.

return Input.GetButtonDown("Jump");

However, with the new system and some of the info from your videos,

bool _JumpPressed;
bool _JumpReleased;

(...)

controls.Gameplay.Jump.performed += ctx =>
        {
            if (ctx.ReadValueAsButton())
            {
                _JumpPressed = true;
                _JumpReleased = false;
            }
            else if (!ctx.ReadValueAsButton())
            {
                _JumpPressed = false;
                _JumpReleased = true;
            }
        };

(...)

public bool GetJump(bool Down)
    {
            if (Down)
            {
                return _JumpPressed;
            }
            else
            {
                return _JumpReleased;
            }
    }

_JumpPressed will be true unless i release the Jump button, which is exactly what happens with the old Input.GetButton, but it isn’t what i need (GetButtonDown)

This code is located on my GameManager, so that’s why i have GetJump(); In my PlayerMovement code i have:

desiredJump = GameManager.GetJump(down);
jumpReleased = GameManager.GetJump;

So i end up with desiredJump always true.

have you tried using press interaction?
https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/Interactions.html#press

Yes, i have my Jump button as Press and Release.

I tried it with Tap too, which almost works, because i need to release the button before the next Jump, but it’s not the behaviour i wanted. The old Input.GetButtonDown worked just fine, with Tap i can get fake presses.

I need to make a new video! :smile: Comin up heh.

But the gist of it is this…

public static class InputActionButtonExtensions
{
    public static bool GetButton(this InputAction action) => action.ReadValue<float>() > 0;
    public static bool GetButtonDown(this InputAction action) => action.triggered && action.ReadValue<float>() > 0;
    public static bool GetButtonUp(this InputAction action) => action.triggered && action.ReadValue<float>() == 0;
}

If you use this method, make sure that your Input System settings match. IE: If you want to use these in FixedUpdate, make sure InputSystem is updating in the Fixed Update loop.

Also make sure you have the Press Interaction set to “Press and Release” when using this method

7 Likes

hmm, maybe, try seperating the action to jumPress and jumpRelease then only use the respective pressonly and release only

THANK YOU!!! Seriously, Unity needs to take a look at this. Is exactly like the previous behaviour, and its waaaaay easier than the current how is explained on the documentation.

Million thanks, you just saved my day.

2 Likes

Welcome!

It’s worth noting that there are some edge cases with this in regards to using things like Gamepad Triggers as “Buttons”. Those extension methods don’t take the “Press Point” into account at all (ie: does a half-trigger pull resulting in 0.5f mean pressed?) But for the majority of button cases they’ll get the job done :slight_smile:

@Rene-Damm :slight_smile:

new input system is too fucked up everyone. who made it? fire him please?

4 Likes

It takes a minute to read up on! It is definitely an improvement over the OG input system in 99% of cases. Now that Unity Remote is mostly working there aren’t many big killer issues anymore. Your forum acct is as old as mine - can I help you with anything in particular? (I’m on Unity discord as @AngryArugula )

I agree with this person ^ ^ ^ ^

1 Like

so how to use above extension?

copy paste above code to somewhere in my script, then what?

if I want to receive gamepad (nintendo switch pro)'s many buttons, like x, y, a, b, r, l, zr, zl, then how?

Gamepad.current.buttonEast.GetButtonDown? but buttonEast. then next, there is no GetButtonDown function.

If anyone is still having issues I found an easier solution.

        private void DoCrouch(InputAction.CallbackContext _obj)
        {
           if(_obj.performed)
           {
             crouch = !crouch;
           }
        }

this will toggle the button true or false each press.