Search Unity

Recommended Input System?

Discussion in 'General Discussion' started by frosted, Sep 15, 2021.

  1. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    Current project wants release on consoles, switch and PC. Normally, I hand roll input systems, but I've only worked on mouse and keyboard input schemes, so it's pretty straight forward.

    For controller support and the like - what are your recommendations (and any pros/cons you've experienced).

    Is the new UT input system good (new being a few years old now I think), or do you lean towards an asset or what?
     
  2. stain2319

    stain2319

    Joined:
    Mar 2, 2020
    Posts:
    417
    The consensus I've seen seems to recommend an asset called "Rewired", by a pretty large margin. I've not used it myself because I've never needed more than simple keyboard input but it seems to be preferred over the native stuff.
     
    frosted likes this.
  3. NotaNaN

    NotaNaN

    Joined:
    Dec 14, 2018
    Posts:
    325
    Unity's new Input System is very capable now with bugs being squashed left and right and a new major release on the horizon.

    However, Unity's new Input System is hard to master. If you decide to use it for a complex local-multiplayer project, you will definitely need to spend some time reading the documentation, researching, and asking questions on the forums.

    As for single-player projects — Unity's new Input System is a very good choice for your input solution. In my opinion, once you learn the ropes and become accustomed to its kinda wonky API, Unity's new Input Solution is actually pretty fantastic!
     
    Last edited: Sep 15, 2021
    frosted likes this.
  4. Pixelith

    Pixelith

    Joined:
    Jun 24, 2014
    Posts:
    580
    I personally use Unity's New Input System and love it. I've never used ReWired though so who knows, I'm probably missing out.
     
  5. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,190
    I have to agree with those that are recommending the new Input System. There is definitely a learning curve to it and the documentation is sparse but it's a sensible system and once I understood the basics I was able to quickly pick up the rest. Getting it working for multiplayer was only slightly more effort over single player.
     
    Last edited: Sep 15, 2021
    NotaNaN likes this.
  6. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I use new Input System. It's very simple to poll in code, and easier than the old built in one. I have used rewired and others, but see no need to now. New input is over-engineered for some things but you can navigate around it.

    The important part is that it works very well, and so far for me, that's the case.
     
    NotaNaN likes this.
  7. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    So here's an example use case, let's say I got a standard 3rd person aim system.

    For controller: stay in aim mode while right trigger is held down.
    For keyboard/mouse: key press is a mode toggle between aim and default.

    What's the approach you would use in the unity input system (or any other for that matter)?
     
  8. Pixelith

    Pixelith

    Joined:
    Jun 24, 2014
    Posts:
    580
    Off the head code but
    Code (CSharp):
    1. public bool toggle = false;
    2. public void OnAimAction(InputAction.CallbackContext ctx){
    3.    if(ctx.performed){
    4.        if(toggle){
    5.          isAiming = !isAiming;
    6.        } else{
    7.        isAiming = true;
    8.        }
    9.    } else if(ctx.cancelled){
    10.       if(!toggle){
    11.       isAiming = false;
    12.       }
    13.    }
    14. }
    would be a super simple example of how to handle it using the new input system.
     
    frosted likes this.
  9. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    The InputSystem actually provides multiple ways. The catch is that the documentation is riddled with holes.
     
  10. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.InputSystem;
    3.  
    4. public class MyPlayerScript : MonoBehaviour
    5. {
    6.     void FixedUpdate()
    7.     {
    8.         var gamepad = Gamepad.current;
    9.         if (gamepad == null)
    10.             return; // No gamepad connected.
    11.  
    12.         if (gamepad.rightTrigger.wasPressedThisFrame)
    13.         {
    14.             // 'Use' code here
    15.         }
    16.  
    17.         Vector2 move = gamepad.leftStick.ReadValue();
    18.         // 'Move' code here
    19.     }
    20. }
    https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/QuickStartGuide.html
    That is as simple and straightforward as it gets.
     
  11. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    It is simple at first, yes, but I wouldn't code my game's input that way because it'll become a pain as dev goes on.

    Hard-coding the "use" code to the physical control has a bunch of downsides, and basically skips out on most of the advantages this type of system gives you. Writing cross-platform code that way would be a huge pain, because you'd need to separately check each different type of device which may be connected.

    The intent is that you define an "action". The action is then bound to one or more physical inputs, but your code doesn't have to care about any of them. All it cares about is whether or not the action was triggered this frame.

    I'm sure you already knew all of that, it's more for frosted's benefit.
     
  12. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    So the approach I'd probably want to use would look something like (freehand code, forgive):
    Code (csharp):
    1.  
    2. bool IsToggle = Gamepad.current == null; // possibly just default in options based on gamepad
    3.  
    4. if( IsToggle ){ if( input.AimToggle.WasPressedThisFrame ) // do toggle stuff }
    5. else if( input.AimTrigger.IsPressed ) // do aim
    6.  
    Or something like that? Or do I want to think about this differently?
     
  13. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,571
    This piece of code is a royally bad idea as it makes an assumption that there's left stick on gamepad.
    Same goes for the "amazing idea" of defining a field for every key on keyboard as a property.
     
  14. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    So I moved everything over to the new input system.

    Agree with you all, they did a great job. Big fan.
     
    NotaNaN and Lurking-Ninja like this.
  15. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    You can just replace those with the relevant reference to an action and it all makes sense as you'd like.
     
  16. runner78

    runner78

    Joined:
    Mar 14, 2015
    Posts:
    792
    Input handling in Fixed Update is also a bad idea, since the method can be triggered several times or not at all in a frame.
     
    neginfinity likes this.
  17. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    What are you doing with it so far?

    I found that doing the simple stuff (making actions in their UI, binding them to stuff, and then integrating those actions into my code) was all nice. That was already better than the old system, so that's a win.

    But after that, there are bugs and documentation gaps which have been known about for well over a year and are still not addressed. I can not fathom why this situation is tolerated internally for a variety of reasons. Input is mission critical to literally every single project ever done with their engine.

    Which reminds me. I solved a thing, so I should find the forum thread where other people were asking about it and share the answer...

    Edit: Oh, and in @hippocoder 's defence, the code he posted is from the manual.
     
    Last edited: Sep 17, 2021
  18. runner78

    runner78

    Joined:
    Mar 14, 2015
    Posts:
    792
    It was changed in 1.1 docs:
    https://docs.unity3d.com/Packages/com.unity.inputsystem@1.1/manual/QuickStartGuide.html
     
  19. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Yeah Unity sort it out :D
     
    angrypenguin likes this.
  20. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,571
    Yup. If fps drops below physics rate, things will get interesting. Or if it goes above physics rate.

    (May result in jerky movement)
     
  21. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    If it is called in the first fixed update of a queued amount (if it has to catch up) then it's still absolutely fine. And you probably could flush it but this is definitely a behaviour @Rene-Damm might want to look at or even address in the up-coming docs.

    I would think the behaviour for frame-based queries (pressed this frame etc) be flushed after the first FixedUpdate between each Update, I guess, as polling doesn't actually need to follow physics stepping, but be in sync for the first.

    I currently am using FixedUpdate polling for reasons in one of my projects!
     
    NotaNaN and angrypenguin like this.
  22. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Yeah, I haven't checked Unity's new one because it doesn't effect me, but there's no reason an input API can't support FixedUpdate(), and some do.

    And for some input types it would work just fine anyway.
     
  23. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Yeah I don't actually use pressed this frame stuff as it seems like a crappy pattern to me. Instead I gather the inputs I require from held presses and any first presses are handled by my own code, at when I choose to handle them.
     
  24. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,571
    It is not about frame-related queries, it is about smooth movement like camera orbiting around player.

    If your physics run at 50 fps, and the game is running at 120 fps, then while the player is moving the mouse, the rotation will be done every few frames which will result in lowfps movement which will look jerky compared to everything else in the world.

    Obviously this will only be the case when you're using the classic pattern of getting mouse delta and rotating based on that. A camera controlled by analog sticks, by the way, will not have this sort of problem.
     
  25. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    But this is what interpolation is for. Most AAA games will use a strategy of updating things far less than they are, and interpolating the result. In fact the first time I encountered this was back in the 90s, and I've encountered it regularly ever since, so no, this is never a problem.

    In DOTS you'll find it's the same story as well, it's just a really common pattern. The idea you want to do a full calculation or step in the game, every frame is not happening. Look at multiplayer?
     
    NotaNaN likes this.
  26. runner78

    runner78

    Joined:
    Mar 14, 2015
    Posts:
    792
    This also applies to the old input system. Inputs are processed per frame, but as mentioned before, FixedUpdate can be called multiple times or not at all per frame, so KeyUp / Keydown inputs can be lost and continuous inputs can become inconsistent.
    https://forum.unity.com/threads/the-truth-about-fixedupdate.231637/
     
  27. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Yeah, I'm fully aware of how the old one works, and about how updates work. :)

    My point is that there is no technical reason that an input system needs to work that way. Just because the old one did is no reason that the new one has to. See Rewired as an example.
     
  28. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    The new system has options:

    upload_2021-9-17_14-3-52.png

    But like yeah I wouldn't move processing to FixedUpdate, that sounds awful. But polling input in FixedUpdate is fine if you poll stuff like IsDown instead of WasPressedThisFrame.
     
  29. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    If you want it to be smooth then it probably should be decoupled from input anyway. You can't rely on the input to be noise free, and if you want to do stuff like follow a physics object then it has to also account for update differences from other sources.

    That rabbit hole leads far, far from the original question, though.
     
  30. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,571
    Is what you're going to have to do when you're controlling the camera.

    Many things can wait or be interpolated, but not this one. (people hate mouse smoothing or jagged camera movement)

    No, you only need to process results from pointer devices at the speed of rendering or faster.
     
  31. MadeFromPolygons

    MadeFromPolygons

    Joined:
    Oct 5, 2013
    Posts:
    3,982
    Haha nicely spotted :D
     
    angrypenguin likes this.
  32. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    If you want maximum responsiveness, yes, but that's definitely can't be relied upon to be "smooth". It's going to pass any input noise straight into the game.

    Personally, that's what I want when I'm using my mouse in an FPS. But that's also not what I'd describe as "smooth".
     
  33. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,571
    ...

    If you place camera controlling code into FixedUpdate and your game will run at high fps, then while you're trying to move the mouse continuously, it'll turn during one frame, and then wait several rendering frames during which the world will continue to animate. That will result in movement that does not feel right. And that's why it is not recommended to put certain types of input code into fixed update.
     
  34. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Mice and head displays can't be interpolated (VR) but everything else can and probably should be. My context didn't involve mice or headset data, which should be calculated as close to the render time as possible to reduce latency.

    The mouse's results will need filtering before being passed to the camera code. The filtering can be very subtle but I've yet to play a polished game where the results aren't doctored in some way as the noise can be intolerable on some devices but not others, depending on the quality of the hardware, and the framerate.
     
  35. runner78

    runner78

    Joined:
    Mar 14, 2015
    Posts:
    792
    And even if the inputs are only processed in the fixed update, the camera would have to be handled in the update method for fluid movements. Then you can do everything in update right away.
     
  36. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Apologies, I missed the word "pointer" or similar in one of the previous posts. Yes, for direct mouse movement, I agree. I was talking about having smooth camera movement in general cases, where it's often not controlled by a mouse, and is often influenced by more factors than just player input (eg: I specifically mentioned following physics objects).
     
    neginfinity likes this.
  37. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    I've basically organized it so it looks like:

    Unity_P7bio79fPx.png

    Each of the action maps basically map directly to a game control state. Player is 3rd person follow, player aiming is when you're targeting a default aim zoom, map selects different characters.

    The rest of my code was largely structured like a state machine (not formally, just organizationally). So these maps map directly to the state logic.

    It was all super easy to work with. Unity_3qiOqSCqUn.png

    Game is still in early phases, so there isn't a ton there at this point, but I think the design is excellent.

    I moved the camera controls to cinemamachine last week, and they play together very well. Each control state has its own set of virtual cameras, its own input map, etc. Very easy to work with.
     
  38. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    Another really nice thing is that the way this is all organized, I should be able to directly expose the input actions to show on screen tooltips for everything. Although that might be more painful than I expect.

    Also I havent gotten to remapping and serialization. One thing I do not like at all is input scaling.

    So I will have a bunch of mouse look inputs (probably like 6) - I need to ballpark scale the input to what feels good. Then I need a player sensitivity slider. It has a scaling option built in but I'm not sure how I should set up player sensitivity to work with that.

    I'd prefer an option to create a custom pre-scaled binding. So like instead of mouse delta, I could set up a scaled mouse delta, and use that directly. Then I could just modify one thing with player sensitivity, etc.
     
  39. Martin_H

    Martin_H

    Joined:
    Jul 11, 2015
    Posts:
    4,436
    Why not wrap the mouse input stuff into your own MyMouse.deltaX etc. and apply the user scaling value there? Makes it easier to switch to a different input solution later too if necessary.