Search Unity

Question How should I properly handle the same physical binding in multiple Action Maps?

Discussion in 'Input System' started by jwvanderbeck, Apr 29, 2023.

  1. jwvanderbeck

    jwvanderbeck

    Joined:
    Dec 4, 2014
    Posts:
    825
    I have two different action maps; Gameplay and BuildMode. They both have an action currently bound to the B key on the keyboard.

    Gameplay/EnableBuildMode and BuildMode/DisableBuildMode

    The intent is pressing B moves you from one ActionMap to the other. When the EnableBuildMode action is fired, I disable the Gamplay actionmap and enable the BuildMode actionmap. And the other way around for DisableBuildMode.

    In my mind this should work as expected. However it does not, and I'm uncertain where I am going wrong here or if this is the completely wrong way to approach it.

    What is actually happening is this:
    upload_2023-4-29_15-0-13.png

    Essentially when I am in BuildMode and press "B" the DisableBuildMode action fires, it then disables the BuildMode actionmap and enables the Gameplay actionmap. As expected. The problem though is that the action "EnableBuildMode" in the newly enabled Gameplay actionmap just suddenly fires on its own. There was only one press of the B key but it looks like the disabled map that was enabled sees it anyway even though it was disabled at the time it was performed.

    I'm not entirely sure I am communicating my confusion well so let me try it in another way:
    I press an action that exists in two action maps. One actionmap is enabled, one is disabled. When the action is pressed, the enabled actionmap sees it and in turn disables itself and enables the other actionmap. Then suddenly the newly enabled actionmap sees the action as performed, even though it was performed while it was disabled.

    Am I making any sense? Probably not :) I find it confusing just trying to explain what is happening.
     
  2. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,445
    So B is currently being held down by the player at the moment you switch to an ActionMap, and this causes the new ActionMap to think it's a new input. It looks like you're just responding to 'performed', not continuously?

    A couple workarounds, I guess: a "cooldown" after entering a mode before allowing it to leave the mode, or don't switch modes until the *release* of the B action instead of the press.
     
  3. jwvanderbeck

    jwvanderbeck

    Joined:
    Dec 4, 2014
    Posts:
    825
    I am responding to Performed yes.
    However "B" is not being held down, it is simply pressed and released.
    Unless everything is just happening so fast that indeed it looks like it is held down to the Input system. That's a good point.

    Shame there is no "Completed" context :(
     
  4. jwvanderbeck

    jwvanderbeck

    Joined:
    Dec 4, 2014
    Posts:
    825
    Ok so I guess "canceled" is the completed context. Seems confusingly phrased but that is what I am seeing. So if I change my code to perform the action on Canceled everything works, though with the user downside of nothing happening until they release the button which makes it feel laggy.
     
  5. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,445
    Yeah, it's almost impossible for a user to press a button for just a single frame. Hardware and device driver debouncing systems are in place to ensure you only get one pulse for a single press, but that also means that pulse is almost always longer than a single frame.
     
  6. jwvanderbeck

    jwvanderbeck

    Joined:
    Dec 4, 2014
    Posts:
    825
    I would have thought delaying a frame would fix it in that case but it didn't :(
    I might need to reengineer the overall flow because I don't like how laggy it feels waiting to perform the action until key up, rather than on key down.
     
  7. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,445
    A "cooldown" would let you have that snappy feel. Take note of the time when you enable each map/mode. Respond on the button press/performed. If it has been more than 0.1f seconds since the action map was enabled, go ahead and perform the switch, otherwise, assume it was being held from the previous mode and ignore it.

    Hey, Unity, it might even be nice for you to have a "time since actionmap enabled" property. Just saying.
     
  8. jwvanderbeck

    jwvanderbeck

    Joined:
    Dec 4, 2014
    Posts:
    825
    Yeah definitely ways to solve it, just as I said I need to re-engineer some things because my current design essentially sees an action then sends an event and everything responds to that event. There is no mechanism currently in my system for different parts of the process to respond at different times :)