I'm attempting to upgrade my technique from the classic input methods to the new Input System for Unity; but I'm finding it a little sprawling and unhelpful so far.

I know that if I have an action, let's call it Fire, and I want it to come from a variety of input devices and call a specific function, let's say Obliterate(InputAction.CallbackContext ctx) when it's used, all I have to do is something like this:

controls.Player.Fire.performed += ctx => Obliterate(ctx);

However, what if I'm attempting to detect if the button has been not pressed, but released, possibly after some delay? I can't find anything on that, maybe I'm overlooking it. Can someone give me a hand?


2 Answers 2


If you use the Hold Interaction, then the Cancelled event gets called when the button is released, with the Performed event happening if the item is held for the given duration.

Image showing the Hold Interaction

As of Unity 2022.3.10f1 (my current version), Cancelled also gets called on release even after you've held for the full amount of time, which seems counter to Internet wisdom.


OK, here's what I've figured out. The type of the action needs to be Value, not Button or Pass Through—this can be changed in the editor by selecting the action from the list; there's a drop down available in its settings. (Don't forget to save the asset and regenerate the C# code.)

Once this is done, the button behaves more like an axis, and invokes .canceled on its release. For a hold action, you can use a coroutine; simply set a control boolean to true and call StartCoroutine with it in your .performed callback. When the button or control is released, it will trigger .canceled, which can call another function that toggles the boolean back to false, and breaks the internal control loop in your coroutine allowing it to exit.

This allows for one action to be performed for a brief press, and another to be performed after a hold in continuum, until the button is released.

  • 4
    \$\begingroup\$ There are started, performed and canceled events. canceled is called when the input ends, started when input starts, performed - this one isn't necessary called every frame, for example, on gamepad when you move a stick performed is called only when the value changes. There are processors that modify behaviour as well if you add them. I don't understand what you mean by StartCoroutine in performed callback, I feel like that is going to create a non-intended behaviour. \$\endgroup\$ Commented Aug 9, 2022 at 19:50
  • \$\begingroup\$ @CandidMoon_Max_ I think this would be worth writing up as your own answer. \$\endgroup\$
    – DMGregory
    Commented Aug 9, 2022 at 19:54
  • \$\begingroup\$ @CandidMoon_Max_ the coroutine begins after a hold action is performed, doing what I want to be done; and ceases after the button is released with a canceled action. That's all, it's very intentional. \$\endgroup\$ Commented Aug 11, 2022 at 3:32
  • \$\begingroup\$ I am not sure the function signature it's expecting. I changed it to value and now it says Method 'PlayerController.OnSkill1' not found, even though I already have OnSkill1 with the InputAction.CallbackContext ctx as param. \$\endgroup\$
    – pete
    Commented Jun 10, 2023 at 1:48
  • \$\begingroup\$ Figured it out; it expects InputValue instead of context, and can be detected by isPressed \$\endgroup\$
    – pete
    Commented Jun 10, 2023 at 2:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .