Search Unity

Feedback

Discussion in 'Input System' started by Baste, Jan 12, 2019.

  1. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,336
    I recently participated in a long-form game jam, and I've been trying out the new Input system with that just now. It's a 1v1 sports-ish game. I've got some initial items of feedback:

    - Generally, the API seems pretty good at first glance. Being able to access gamepads directly from code without going into the input manager is a large step up for prototyping, and the bindings stuff looks neat.

    - I really miss something like InputDevice.anyPressedThisFrame and InputDevice.anyDown. I wanted to do quick bindings of input device to player, and it would be a lot easier to do (and a lot easier to read) if I could just iterate all input devices and check if anything was pressed on it.

    - Related, I'd love something like InputDevice.all, which did the same thing as GamePad.all. Probably also Keyboard.all.

    - ReadOnlyArray is neat, and should really be a standard utility rather than something tied to InputSystem. Or is it just a placeholder until Slice becomes generally available?

    - This issue is just horribly confusing.
    controller.leftStick.ReadValue().x
    should really not be different from
    controller.leftStick.x.ReadValue()
    . I don't think both need to exist, really.
     
  2. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Would have expected identical functionality and would have definately gotten confused which is which - repeatedly. One must go :)

    FWIW my own input manager looks like this for querying:

    float x = input.leftStick.value.x; (exposed vector2 that's updated). I mean, yep, super simple but I love how easy it is to code with. As AI also use this class and make dummy virtual controllers that are super lightweight I would love to have similarly easy and simple access.
     
  3. Code (CSharp):
    1. Debug.Log(Keyboard.current.anyKey.isPressed);
    Isn't this the same? Obviously if you have more than one device, the current should be replaced with the proper device.

    I can't really test it with gamepads right now, because they're in a box somewhere (I recently moved). But I know we have something like this (I don't know if it works properly or not):
    Code (CSharp):
    1.             for(int i = 0; i < InputSystem.devices.Count - 1; i++)
    2.             {
    3.                 Debug.Log(InputSystem.devices[i].name);
    4.  
    5.             }
    6.  
    I vote for this. Having a compound Vector2 is always better (because the elements can be used separately too).

    ps: it is a possibility that I misunderstood something, I'm in the middle of my first coffee, so I'm not really on the normal, working capacity just yet. :D
     
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,336
    I was thinking of something that means "any button/key" on any device - so it would register if the user hit the keyboard, the gamepad, the adaptive controller, whatever. At minimum, Gamepad.anyButton would be nice.

    Generally, it'd be for something like the a local-coop game or arcade game, where if a controller is touched, it's assigned to a player. I tried (thanks, btw):

    Code (csharp):
    1. for (int i = 0; i < InputSystem.devices.Count; i++)
    2. {
    3.     var device = InputSystem.devices[i];
    4.     foreach (var inputControl in device.allControls)
    5.     {
    6.         if (inputControl is ButtonControl &&  !inputControl.CheckStateIsAtDefault())
    7.         {
    8.             Debug.Log(device.name + "; " + inputControl.name);
    9.         }
    10.     }
    11. }
    But axis controls are also button controls, and this doesn't have any deadzoning involved, so my xbox controllers are continually spamming. It's also a "down" rather than "downThisFrame" check.

    There's probably a better way to do this that I haven't found.

    Generally, I think deadzoning should be applied at a much deeper level. If I've applied deadzones in general, it's confusing that a lot of views of controls that are deadzoned actually give raw views. If I'm checking if an input device's state "is at default", I probably don't care about noise?
     
    Last edited: Jan 13, 2019
    Lurking-Ninja likes this.
  5. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,336
    Another thing I noticed, possibly bug: When the Game View doesn't have focus, my xbox controller's stick movement is picked up by the game, but not buttons.
     
  6. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,336
    Bug:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.Experimental.Input;
    4.  
    5. public class TestScript : MonoBehaviour
    6. {
    7.     void Update()
    8.     {
    9.         Debug.Log(Keyboard.current.leftAltKey.isPressed);
    10.     }
    11. }
    12.  
    Alt-tab out of Unity, and then back in. "True" will be printed until the next time you hit alt.
     
  7. Actually it would be nice universally for example to run remap settings page. LIke remap Shoot (enter), then "hit any key or button". And you can wait for the first button or key pressed either on the keyboard on the mouse or on a gamepad/joy and you can remap that to the action. Better than long lists of possible keys/buttons.
    So I think for desktop games on settings it is really unavoidable if we want to support both keyboard/mouse and any kind of controller.
     
  8. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Thanks for the feedback! Always appreciated to get tried-it-and-heres-my-thoughts.

    Could you post a code snippet of what you'd like that to look like in your code?

    I like that. There's InputSystem.devices and InputDevice.all would be equivalent but it seems it'd improve discoverability.

    Oh boy, this.one. I really wish we would be further ahead here than we are.

    Short answer: Hopefully it'll become part of shared API. No immediate plans, but surely hopes.

    Long answer: The transition to packages is a pretty massive shift for Unity development-wise. And being a very engineering-driven company, we tend to not be the most awesome coordinators of things so the transition is a little rougher than it probably has to be. We're getting better there but changes that require good coordination across large areas of R&D still tend to be bumpy.

    In the past, if we needed something that's shared between all of Unity, well, you'd just put it somewhere in a good place in the runtime or editor code outside of just your feature. Now, with packages, we've only just begun to figure out how to handle that kind of stuff which unfortunately in the transition period, we're seeing some stuff like ReadOnlyArray that clearly shouldn't be confined to one package yet ends up there.

    On the confusingness I agree. On the necessity for both I don't.

    Having processors also propagate *down* the hierarchy rather than only up is on the list. It is indeed confusing the way it is ATM. Hope we'll get to it before 1.0-preview, but there's a chance it won't make the first release.

    I think the need to have both is there, though. There's situations where it's great to be able to bind horizontal and vertical independent of the whole control. Say you have a strategy game where the camera can only swivel and you want to drive it from rightStick/x and a QA 1D Axis composite.

    But yeah, without deadzoning also affecting X and Y, that functionality isn't complete.

    At an action level, this is easy to do. Though not necessarily super efficient ATM.

    You can bind to "<Gamepad>/<Button>". ATM requires dropping the UI into text edit mode (that weird "..." button; up for a UX pass, too). ATM also only catches buttons at the toplevel of the device. Eventually, the plan is to be able to do "<Gamepad>/**/<Button>" to query arbitrarily deep into the hierarchy. Put a "Press" modifier on the binding to get rid of axis noise.

    As far as joining is concerned, my hope is that the APIs will obsolete any need to manually roll your own logic there.

    At the low-level, there's InputUser which has support for telling you whether an unpaired device was used.

    Code (CSharp):
    1. InputUser.listenForUnpairedDeviceActivity = true;
    2.  
    3. InputUser.onUnpairedDeviceUsed +=
    4.     control =>
    5.     {
    6.         var button = control as ButtonControl;
    7.         if (button == null)
    8.             return;
    9.  
    10.         JoinPlayer(button.device);
    11.     };
    The API takes care of catching meaningful user interaction rather than device noise.

    At the high-level, there's an emerging component in the form of PlayerInputManager which is meant to make setting up player-joins a one-click affair and should obsolete the need of talking to InputUser directly.

    My goal is to be able to convert the Survival Shooter demo into a four player local co-op game with split-screen using the new input system and without writing code.

    I think this is mainly about the API making it very confusing which level you are operating at by having all the methods sitting side-by-side on the same set of classes. CheckStateIsAtDefault() for example is a very low-level method that performs a cheap pure memory check that just memcmps the current state of the control in memory to the stored default state for it.

    The API tries to make the distinction clear by talking about "state" whenever it talks raw memory and talking about "value" whenever it talks processed values.

    But this requires a deeper understanding of the inner workings than should be required to use the APIs. So, room for improvement.

    Also, the method to check "is value at default" is missing. I'll add that.

    Does sound buggy. Created a ticket here.

    We have some pending native changes that should fix this. Current 2018.3 doesn't properly handle focus. Backport should be landing sometime soon.

    My hope is that no one will have to drop that low and manually code that kind of logic. InputAction.PerformInteractiveRebinding() and the stuff in InputActionRebindingExtensions.RebindOperation should take care of this kind of stuff. Somewhat confusingly, the stuff can even be used if you don't have an action and want to just listen for input from the user.
     
    Last edited: Jan 14, 2019
    Lurking-Ninja likes this.
  9. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,336
    Actually, the InputUser.onUnpairedDeviceUsed thing you posted was exactly what I was looking for. I'll also take a look at the InputAction.PerformInteractiveRebinding() things you posted, and see if I can make a rebind thing quickly.


    About the "any key down" stuff, here's an example from a recent game jam game using the old Input system where converting to the new one made things a bit clunkier:

    Code (csharp):
    1. public void ShowCredits() {
    2.     mainMenu.gameObject.SetActive(false);
    3.     credits.gameObject.SetActive(true);
    4.  
    5.     StartCoroutine(ReturnToMainMenu());
    6.  
    7.     IEnumerator ReturnToMainMenu() {
    8.         yield return new WaitUntil(() => Input.anyKeyDown);
    9.  
    10.         mainMenu.gameObject.SetActive(true);
    11.         credits.gameObject.SetActive(false);
    12.     }
    13. }
    Input.anyKeyDown works for controllers as well as keyboards, so that's a very compact way to check for something like that. As far as I can tell, there's nothing as straight forwards in the current new input system - you have to set up bindings or whatnot.

    I think it should still be possible? Especially for situations where you have strange control schemes, or maybe are restoring keybinds from a custom serialization format. PerformInteractiveRebinding looks really good, but sometimes you just have to drop really low level for whatever reason.
     
  10. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Hmm, good point. I'll have a think about this and see how we could get a similar API in place. The way events work in the system makes listening for *specific* changes that could happen *anywhere* kinda costly so it'd probably not be as super simple as Input.anyKeyDown but hopefully we can have something pretty close.

    Oh absolutely. Don't mean that no one should be *able* to drop that low, just that hopefully no one *has* too :) The APIs there internally just use other public APIs so it's built on stuff that is available to the user as well. The rebinding stuff in particular is just one big wrapper around InputSystem.onEvent.
     
  11. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,336
    If there are minor issues (like "delete" not working in the input manager window), should I post it here or just raise an issue on the github?
     
  12. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,336
    Thoughts on the input action assets and their editors:

    - I got really confused by why there's a "Press" interaction and a "PressAndRelease" interaction, but no "Release" interaction. After testing, I realized that PressAndRelease sends the press action on "started" and the release action on "performed", but that's not intuitive. Maybe add a "Release" interaction for completeness?

    - There should really be either a .performed or .cancelled callback when the game window loses focus, otherwise it's hard to prevent losing focus causing something like permanently charging an attack. You said upthread that you're working on focus, so that should be a part of it.

    - The way the generated scripts for input action assets work, where they're placed outside the Assets folder without a .cs extension, is strange. Is that just a temp thing, or will it be permanent? I'd prefer for the generated script to be a nested asset of the asset or placed next to it (maybe based on an option).

    - The way the generated script is set up right now, it's a bit too wordy. I've got this test setup:
    upload_2019-1-17_21-16-4.png

    And the code to check Hammer_Pressed is:

    Code (csharp):
    1. myInputs.Inputs.Hammer_Release.started += HammerReleaseOnStarted;
    I think you could dump the Inputs struct, and just let us write:

    Code (csharp):
    1. myInputs.Hammer_Release.started += HammerReleaseOnStarted;
    Preferably we could have both - I can see where having a reference to the Actions struct to pass around that doesn't duplicate the !m_Initialized check could be neat, but I've got a feeling I'm going to be assigning the event and forgetting about it most of the time, in which case the terser input would be nice.

    - Would it be possible to define that an Action could only target buttons in the UI? In that way the generated class could define eg. Hammer_Pressed as a ButtonControl (rather than an InputControl), and I could check things like .wasPressedThisFrame.

    - It seems cumbersome that I have to manually Enable the bindings. Could maybe
    InputActionAssetReference have an "Enable on startup" toggle that could be set from the inspector?

    - It seems like I can't set up composite actions for the input action assets. Is that just not done yet? To be able to set up a UIActionInputModule for keyboard properly, I'd need to set up wasd or arrow keys as the Move action, but I'm not able to bind "Dpad" bindings in the input action assets window.

    - Also the drawer for InputAction is broken and InputActionProperty is super-broken, but I think that's already been reported?




    By the way, this system does look great. It's intuitive to make actions and assign them, and automatic script bindings is a real timesaver.
     
  13. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    GitHub issue preferred.

    The set of interactions needs a consistency and cleanup pass. Currently working on it. What's there ATM has grown very organically so yeah, there's holes and inconsistency.

    I think the focus logic, once backports of native changes have landed everywhere, should improve things but I think for actions, more is needed. Agree that the actions should all cancel on focus loss, except if input is configured to run in the background. Have put it on the list for the next package release.

    Wait, that sounds like a bug. It should place it next to the .inputactions asset by default. And definitely shouldn't generate some random file somewhere without an extension. Can you show me what the importer settings for your action asset look like and where it's located in the project?

    The second form would require all action names to be globally unique in the asset. Not an unreasonable constraint as such but it's not mandated ATM. Action names only need to be unique WRT their map ATM.

    Overall, I'd like to get rid of the entire need to manually fiddle around += and -= in almost all cases. The manual delegate management is a pain in the neck. There's some high-level wrappers coming that should automate most of the action management. For working with the generated C# wrappers, I recommend checking out the "Generate Interfaces" workflow described in the quick start guide here.

    You can constrain the type of an action from its properties. Set "Type" to "Button" to allow it bind only to button controls. This will also get rid of all the non-button controls when selecting controls in the control picker.

    ATM there's no effect on the generated C# code. You can safely cast to ButtonControl in action responses, though.

    Note, however, that using .wasPressedThisFrame from an action should never be useful. In fact, it's probably a bad idea. Actions don't care about frames the same way. If a button goes down and up and down and up in the same frame, you'll get two clean presses whereas .wasPressedThisFrame registers only one.

    There is the annoying problem of getting *two* callbacks instead of one. One on press and one on release. I'm about to introduce a breaking change that alters this behavior such that on a binding without an interaction set on it, if a button goes down, you get .started and then .performed and then a .cancelled when the button is released. This should generally obsolete the need to use the Press interaction.

    So, an attack on this front is in full force :) Essentially, some of the most consistent feedback about the action stuff has been that it's pretty straightforward to set up the actions and bindings but very tedious and complicated to do the scripting side. My declared goal is to be able to take a project like the Survival Shooter and the new input system and go from zero to full setup in less than 10 minutes with little to no scripting. And definitely no tedious Enable/Disable or +=/-= stuff.

    That said, there's probably also opportunity to add some nice little helpers to the various things like InputActionAssetReference along the lines you're thinking of. I've made a note.

    This is with actions directly on the module? Could you file a bug on GitHub?

    The actions-on-components workflow has seen little testing compared to the action asset editor but no excuse there. Overall expectation here is that things are just as functional as in the full UI.

    Just to make sure, could you file a bug for this, too?

    Glad to hear :)
     
  14. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,336
    I'll post the issues, probably today, maybe.

    @Lurking-Ninja posted how to do this in this thread. I should've given the full path.
    That's probably not what you want to do - but whatever you end up doing for how to specify the path, the interface should show what the final, full path is.
     
  15. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,336
    It was in the input manager window. Testing it today, I was wrong, and I can totally make d-pad bindings. No idea why I thought I couldn't last time?

    EDIT:

    Nope, can't reproduce this either. Last knight the fields in the list for a InputAction or InputActionMap got positioned at y-0 of the inspector instead of where they should be (ie over the name of the gameobject): Today they're well-behaved. No idea what's changed.
     
    Last edited: Jan 19, 2019
  16. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Awesome, thanks.

    Ah yup, this should indeed be relative to Assets/. Ticketed.

    Hmm, the two irreproducibles still make me think we probably got some issues here. Let's see :)
     
  17. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,336
    We for sure do, I found an issue on github with a screenshot showing exactly one of the bugs I had.
     
  18. AshMcConnell

    AshMcConnell

    Joined:
    Aug 10, 2011
    Posts:
    11
    Hi Rene, are you intending to include player specific menus? It's something I'm having difficulty with in the current Input + Event System. Is the intention to allow multiple selected menu items in the new Event System?

    Thanks!
     
  19. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Yes, allowing separate UIs to be driven separately from devices is the intention. Still some work to do. We may still run into some problems there with the built-in event stuff but should all be solvable.
     
  20. AshMcConnell

    AshMcConnell

    Joined:
    Aug 10, 2011
    Posts:
    11
    Brilliant! That will be perfect :). I think I'll have to roll my own basic menu navigation in the mean-time, but can't wait to try it out when it become stable!