Search Unity

It seems a bit over complicated - why not just keep it simple?

Discussion in 'Input System' started by darbotron, Jun 20, 2016.

  1. darbotron

    darbotron

    Joined:
    Aug 9, 2010
    Posts:
    352
    I've been involved in writing and maintaining several in-house engines across many platforms over the last 20 years and I've also ported Unity games from PC to current gen consoles.

    The one thing I do really like in the design is that it has the concept of players and controller ownership in it - this is a big deal and the biggest problem I have with the current Input system its its lack of accounting for this.

    The player/controller view should make porting Unity games to console a lot less painful than it is currently - though I would argue that player specific controllers should probably be the default for a single player game rather than using a global controller (again, it makes little difference to PC but fits better with a console world view).

    One specific thing that really does seem like a bad idea to me is the event based controller system. In my experience, callback style interfaces sort of actively encourage naive users to write code that is likely to contain timing related bugs. I think it would be much safer (& AFAIK offer the same advantages) to simply be able to iterate the control state changes that have occurred on a given controller since last update frame in the order in which they happened (with timestamps I guess)? Incidentally, being able to store these to a buffer and replay them later via a "ReplayController" would give you replays "for free" (assuming a constant framerate in the game)...

    So, the main thing that I wanted to say is that, having spent months of my life writing complex systems not dissimilar from this one; the biggest, and possibly most surprising, thing that I have learned about these input systems is that they don't need to be complicated, and in fact I would argue that they should be as simple as possible.

    Here's why I think this: game specific code which reads input from input devices and processes it into a form for game logic to use to make decisions is generally written approximately once per project.

    I totally get that this is trying to make it easy for people to set up complicated control systems with the smallest amount of code, but (again, in my experience) despite having spent months of my life writing complex systems not dissimilar from this one, I have found that in general a large proportion of the stuff that gets assumed is required in input libraries is just not necessary.

    All that is happens when you do this is that instead of the control complexity residing in a couple of relatively simple one-off game specific classes, you end up creating a system which has enough layers of data driven generic abstraction to be able to create the same level of complexity as all games' simple one-off game specific controller reading code.

    In order to meet these constraints the various layers of editor code and data will probably end up approximating a half-finished Turing complete language; but instead of a few functions of easily debuggable game specific code we now have a bunch of similarly complex behaviour pushed out into an either non-debuggable or hard-to-debug probably partly implicit data driven system.

    On top of this the system just won't fit the specific requirements of most control systems perfectly - no matter how well designed or how well intentioned & well thought out the abstractions are. The upshot of this (in my experience) is that approximately the same amount of game specific control code will need to be written to stitch around the edges of the generic controller system as if a simpler, less data driven, approach were used.

    The saddest irony of all this is that this ends up making a massive rod for the maintainer's back supporting it all too, despite the fact that - since the game specific code only needs writing once per game - the necessary "85% solution" to the problem could be accomplished with direct access to the controllers and a bunch of simple helper classes to (for example) combine raw inputs into axes, deadzone axes, provide mappings to allow the various controls to be accessed via enums (or other name), and maybe a tutorial showing how to create a UI for in-game remapping etc.

    Ultimately it's Unity's call how complicated and data driven it wants to go, but personally I would be trying to think how to make this stuff as simple and lightweight as possible and concentrate on providing a few great tutorial projects showing how to use it to do more complex stuff like remappable input sources - otherwise you'll just be spending the next 5 years adding tiny feature after tiny feature to it and chasing around fixing the weird edge cases that people find when they try to use it (mechanim anyone?).

    All the best,

    Alex
     
  2. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    Hi Alex,

    I appreciate the feedback but I need some clarifications to properly understand it.

    The new Input System consistent of a lot of parts that solve various problems and build on top of each other. I'm unsure which of them you're talking about when you're saying it's too complicated.
    • Input Device classes
    • Standardization of common control types (such as gamepads) using device profiles (devs most often won't need to worry about this).
    • Action Maps for specifying high level actions that can use multiple different control schemes
    • PlayerHandles
      • for keeping track of which devices are assigned to which players
      • for keeping track of active ActionsMaps for a given Player
    • PlayerInput components for easily setting up PlayerHandles without too much scripting
    Input can be queried in multiple ways.
    • Querying control state directly on an InputDevice (e.g. what's the values of the left stick of Gamepad #2?)
    • Querying action state through ActionMapInstances
    • Listening to control events directly for a given input device
    • (Planned but not yet implemented) Listening to action state change events on ActionMapInstances
    Every one of the abilities have been added due to explicit recurring demand.

    When you say the event based controller system, what do you mean? In the recommended common way of using the system, ActionMapInstances listen to events as an implementation detail, but as a develop you'd query the current state of the ActionMapInstances through a polling API. We've gotten requests though to also be able to get this in the form of events, so we're planning to add that.

    We never strive for complexity; we always strive for simplicity. But simplicity can mean many things and different things to different people.

    For some, a system that does as little as possible is simple. It may require for you to do a lot of stuff yourself, but that may be fine to you. For others, simplicity means having to do as little as possible. We're trying to do both of these. If you want a system that does less, you can use the more low-level aspects of the system (like querying input from input devices directly or even listen to events directly) and disregard the optional higher level parts of the system like ActionMaps and PlayerHandles.

    But it sounds like you do like the device assignment aspect of player handles, which is actually a high level concept. Everyone have their own idea of what simplicity means for them.

    If you can explain a bit more how you'd want to ideally use an input system, maybe with code example of how you'd like to invoke API to handle player assignment and handling input for your gameplay logic, that might help me better understand which kind of simplicity you have in mind.
     
    sand_lantern and Alverik like this.
  3. darbotron

    darbotron

    Joined:
    Aug 9, 2010
    Posts:
    352
    Hey Rune,

    All I'm really saying re: complexity is that I think you're making a massive rod for your own back in terms of user support and the stuff that people will expect to "just work" especially when IMO you can get to (say, for the sake of argument) 85% of this with far less code complexity and burden of support on you, and then just supply a couple of sample and / or open source tutorial projects that sit on top of it which show how to make it do complex stuff & maybe even allow people to just drag in an asset package that adds that to their project.

    I also get that this approach might not fit in with Unity's way of doing things.

    I'd disagree fairly strongly that a player handle is a high level concept - for both current and last gen console dev (user + controller + save data) embodies "user identity" which is a core concept of their operating systems and 100% required in order to ship a console title.

    I'm super busy on-site with a client right now, will get back to you with a quick sketch of the way I'd like a pad library to work & how I'd want to use it - I meant to give you a bunch of sketched out classes but it was late - also your work on this and reply are both immensely appreciated ;)

    Alex
     
    Last edited: Jun 21, 2016
  4. darbotron

    darbotron

    Joined:
    Aug 9, 2010
    Posts:
    352
    Hey Rune.

    Have spent ages thinking about this & not finding time to get back to you, sorry.

    Ironically, I've been writing a multiplatform PC / console controller layer built on top of the existing unity Input system...

    It's not that far from what you outlined in yr reply of 21st June really, but the differences are important (IMO).

    My idea of a player handle is something different - more of an OS level view (who's logged in, which controller is their 'active' controller, have we got a valid save location).

    I still think that event driven control code is a terrible idea & I'd like to see a use case made for it which doesn't make code potentially much less safe and which isn't doable with regular polled input; but I think that's a subject for another time / topic ;)

    From your system I'm probably only ever going to need these 2 layers:
    This is the kind of thing that, if we had a meeting room with a whiteboard we could discuss this in about 30 mins and whilst we might end up disagreeing still at the end of it, we'd at least understand where each other were coming from better :)

    Rather than 'action maps' I'd prefer a thin layer on top of your 2nd layer, something like: (names are super-placeholder)

    GameControllerDefinition - essentially a container for a template abstracted view of the hardware inputs that a game might need, contains 0 or more of each of the following:
    • ControllerButton (abstracts input from 1 hardware button or a thresholded hardware axis)
    • ControllerAxis (abstracts input from 1 hardware axis or 2 ControllerButton)
    • ControllerStick (abstracts input from 2 ControllerAxis)
    • other inputs like touch screens etc.
    A GameControllerInstance would be created at runtime from from a GameControllerDefinition and would be associated with either a hardware controller or a virtual controller (e.g. replay data previously recorded from a hardware controller, or an AI player) to get its input from.

    In addition a GameControllerDefinition would have an optional associated GameControllerRemapper that, if present, could be used to change the inputs to some or all of the Controllerxxx objects contained by its parent GameControllerInstance.

    I'd also want to see a bunch of UI components which interact with GameControllerRemapper to simplify making an in-game menu to remap the inputs of a GameControllerInstance. This could be given away as a sample project.

    The game's "action map" would get embedded in the code interface that client code used to access the various Controllerxxx classes.

    e.g. you might have a class called GameInput which had a member function Vector2 GetMoveControl() which then returned the Vector2 by using an internal GameControllerInstance containing a ControllerStick called Move and calling Move.GetStickVector().

    This GameInput class would probably only writing once at the beginning of the project, so even though it might take a little time it would be insignificant vs. the whole project timeline; it would also all be single-step debuggable by the end user, which having to set up loads of data in the editor just isn't.

    As you say, this stuff is mostly a matter of preference - I just wanted to save you some work if you didn't need to do it; what I'm suggesting seems to me to be quite a lot less work but to offer most of if not all the flexibility of the system you're currently producing; it's just a little more script heavy (and arguably takes longer to understand).

    All the best & hope it goes well, as I'd definitely love to see the existing Input system replaced ASAP ;)

    Alex
     
    Last edited: Jul 4, 2016
    LeonH likes this.
  5. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    Your GameControllerDefinition sound pretty similar to either our ControlSchemes or the ActionMaps that contain the control schemes. It's not clear to me what the differences are other than the names. They do support the equivalent of your ControllerButton, ControllerAxis, and ControllerStick. Your GameControllerInstance sounds like our ActionMapInput objects. I'm sure there are differences compared to what you have in mind, but they were not clear to me based on your description.

    If the InputDevice classes and standardization is all you'd want, you can definitely use only those aspects of the system. It's up to you.

    The work we're doing, we're doing for a reason. We have a long list of things to solve based on input from the community. It's natural that not everyone need every aspect of it.

    Rune
     
    Alverik likes this.
  6. TimHeijden

    TimHeijden

    Joined:
    Mar 5, 2015
    Posts:
    34
    My original post seems to have gotten lost with the transition of the forums back-n-forth. posting it again:

    "
    Hey Alex / Rune,

    I'd just like to weigh in on the complexity / rod you are talking about it.

    In my opinion, an engine should give me many tools/options to handle input, because input is one of the most important things for an engine to handle! Specifically, the thinks I personally think the engine NEEDS to offer me are:
    - Standardized axes / button actions without having to use strings in code
    - Offer support for a great amount of different controller types (if you know InControl, the profiles)
    - A good structure in retrieving and updating these controllers. This includes stuff like: getting a list, connect/disconnect/reconnect events
    - Controller specific features, or a way to implement these myself. Examples: PS4 light, rumble, etc.
    - Being able to rebind controls. Could partially be something I write, but some standard needs to be there. (see first point)

    I feel like Unity has previously made a mistake in trying to not make it very complicated, resulting in the poorly designed system we have been working with for many years. And while alternatives such as Rewired are available, they also lack in the support they can offer on specific platforms due to the limitations they have to work with.

    Example: An IL2CPP issue comes up inside a dll due to a Unity update which the plugin devs have to respond to before I can update.

    Implementing my own version will also take up a lot of time that I simply do not have the budget for. So while you are right, this will be quite the maintenance rod, I believe it is justified in this case.

    Controller ownership is tricky to implement in a generic way, because each OS/platform reacts differently with controller disconnects. For example, the binding between controller & OS user is much tighter on a PS4 compared to an XBOX one. In addition, some games should respond differently to controller events than others. In fact, it can change based on the gamestate!

    This does bring me to a question for RuneVision, to what degree will the input system be open source? My current assumption was that the high level code would be open source, but the low level / C++ side wouldn't be.
    "
     
    darbotron likes this.
  7. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    That's correct.
     
    darbotron and Alverik like this.
  8. greg-h

    greg-h

    Joined:
    Jul 29, 2012
    Posts:
    17
    I agree with OP.

    All of the code I'm looking at starts off by assuming I want to use your new input system. The honest truth is that I don't. Unity has a terrible track record for implementing non-trivial systems that don't have massive fundamental design flaws (see: old UI system, old networking system, old input system, physics engine before most recent overlap queries were added). So immediately, I don't want to use your new input system, because I am already going to assume it will not hold up to any non-trivial design expectations.


    What I do want is to implement the simplest solution that works for my project, and what I would like to see is a no-frills, concrete mechanism for querying input. Give me something like XNA. Let me query the state by gamepad index.

    Give us something like XBox360GamePad.GetState(PlayerIndex.One).IsButtonPressed(XBox360Button.X). Give us Playstation4GamePad.GetState(PlayerIndex.One).IsButtonPressed(Playstation4Button.Square). Don't pass the PS4 touchscreen off as a button. It is a two-point touchpad, correct? Give us an API that let's us query it.

    If I'm only developing for windows, then I'll just use Keyboard.GetState(). If I'm developing for PC and xbox 360, then I'll implement the simplest abstraction that I need. If I'm implementing a game for every console platform and PC that also requires dynamic re-binding, then I might consider using your system.

    If you want to build a data-driven abstraction layer on top of that, that's cool. Build it on top of something simple that *definitely works as advertised* and that you *expose to users*.

    Last few thoughts:

    Please just get rid of the InputManager.asset. It is utter garbage having to edit it.

    Why aren't you using standard C# naming conventions?

    If you're going to implement a demo to test your new input system, do real test cases. An FPS "game" with one button is trivial. If you want to put your new input system to the test, show me an MMO style key-rebinding demo. Show me context-sensitive actions that correctly handle input-blocking transitional animations. Show me an FPS demo with vehicles, or with quick-time events. It seems incredibly naive to implement literally the simplest thing you can possible think of to test this system and think it will cover everybody's use cases.
     
  9. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    I hope venting made you feel better. Now let's get constructive.

    You can do that currently with (Gamepad)InputSystem.LookupDevice(typeof(Gamepad), 0).action1;

    action1 is the X button on 360, and the cross button on Playstation etc. This follows the device standardization approach that is also used in several very popular input solutions on the Asset Store. As for the syntax, we're going to improve on it.

    Yep, the plan is that there will be a Playstation4Gamepad class that inherits from Gamepad and exposes all controls specific to Playstation 4 gamepads.

    Yep, that's what we're doing.

    It's not part of the design of the new input system. We'll keep it for a while for those still using it.

    We're using the naming conventions used in Unity API (if we're not doing that consistently then that will be fixed). As for why Unity API doesn't use all C# naming conventions, that's off-topic in discussion of the new input system.

    The point of making the prototype available at an early stage was to get early feedback. We can't at the same time have massive demos with every thinkable functionality already implemented. Then it would by definition already be a much later stage in development, and it would be harder for us to change course based on feedback at such a point.
     
  10. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    This was changed since the prototype so Gamepad extends from InputDevice directly.

    InputDevice extends from InputControlProvider so that InputDevices and ActionMaps have a common base, and can be used interchangably in some contexts. This makes it easy to start out talking to a Gamepad directly, and then change your mind later if you find you want to implement multiple control schemes via ActionMaps for instance. Since ActionMaps provide controls to work with in the same way that InputDevices do, the required code changes are minimized.

    This has changed since the prototype and this dependency has gone. The entire folders for ActionMaps and Player handling can be deleted and just the InputDevice parts of the InputSystem still compile and and can be used on its own.

    InputControlData has been merged with InputControls since the prototype so there is now only one array of controls instead of parallel arrays with different aspects of controls. We originally attempted to separate static information and dynamic state, but this turned out to not have any real advantages.

    Yep. Basing the system on InputEvents at the lowest level has certain advantages, such as certain things being able to consume an event, and other things then never seeing the corresponding input, since it would give unfortunate behaviour if multiple systems reacted to the same input at the same time.

    The enums are gone; the abstract InputControls are still there. While InputControl is abstract, InputControl<T> is not. Different input controls hold different data types; some floats, others Vector3s or Quaternions. The various InputDevices expose InputControls via properties on the class, where they can be accessed as-is without casting. And when using through an ActionMap, the related systems take care of handling compatibility.

    InputDeviceProfiles were explicitly registered in the prototype but are automatically registered in the current system. InputDeviceProfiles are needed to account for differences in mappings of input devices between different models, manufacturers and operating systems. They are used in e.g. InControl and ReWired too for the same reason.

    What's the problem with that?

    The features that are there have all been added because we had requests for solving various use cases that made these features necessary. But you can easily disregard the majority of it and only use the parts you actually want.

    Sure, in the prototype the InputDevices had a dependency on other modules compilation-wise, but even then it didn't mean you had to use those modules. And now these dependencies have been removed.

    We are always open to feedback, but I would request going forward that you focus the feedback around tasks and workflows from *your* perspective that seem more complicated for *you* to do/perform/code than they need to be, rather than placing your focus on the system architecture as a whole, which are meant to satisfy a broad range of users and not just suit your preferences only.

    I'm not quite sure what you mean. We could have made a demo that speaks directly with Gamepads and doesn't use ActionMaps and that would have been using a much simpler subset of the system, but we prioritized to show the ActionMap approach instead because we believe it has advantages for many users.
     
    Alverik likes this.
  11. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,329
    What does the code look like to poll WASD and an analog gamepad? Then are there facilities to detect certain combinations of keys like say X+O, And what about sequence of keys like combos in Tekken?
     
    Flurgle likes this.
  12. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    Without an ActionMap you'll be able to query the gamepad like this:
    Vector2 vector = Gamepad.current.leftStick.value;

    And a keyboard key like this:
    bool pressed = Keyboard.current.GetControl(KeyCode.A).isHeld;

    If you use an ActionMap where you set up a movement action that is bound to left stick on gamepad and WASD on keyboard, you can just do this:
    Vector2 direction = myActionMap.movement.value;

    Combinations, yes. We have a binding type for that in ActionMaps. Sequences are not yet implemented but it's on our todo list.
     
    Alverik and Too-Nerd-To-Die like this.
  13. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,329
    Great, thanks.
     
    Alverik likes this.
  14. Alverik

    Alverik

    Joined:
    Apr 15, 2016
    Posts:
    417
    I don't agree with the OP. I find it awesome that Unity is trying to get a wide scope of usages for the input system (and most other systems too). If some hardcore programmers don't like it, they can just use the API that they need to make their own system, or write it from scratch (as many of them like to do anyway).

    These kinda of programmers tend to have their own way of doing things, and they're often the type that likes to reinvent the wheel for every game they work on. Personally, I'm my own lead programmer, and I'd rather spend my time designing gameplay, levels and art than redoing all my basic systems for every single game.

    Unless you are a big company, or even if you are, redoing systems every time you start a project is a bad idea. Reusing basic and reliable systems is best, even if they have their limitations (which all systems do at the end). All you have to do is design around those limitations or think up creative ways of getting around them. After all, limitations will always be around.
     
    sand_lantern likes this.
  15. darbotron

    darbotron

    Joined:
    Aug 9, 2010
    Posts:
    352
    I love that you are not only dismissive of my opinion despite the fact it's been formed by over 2 decades of game development experience but are also more than happy to make sweeping generalisations about "these kinda programmers" which other a whole swathe of your potential peers in your quest to own the most correct opinion.

    2/10 for constructive discussion; 8/10 for unhelpful inflammatory remarks.

    However, reading the posts since my last reply it appears that the low level system being implemented does exactly what I expected it to, and that the additional layers will be open sourced so not only do I not have to implement them myself, but if they don't do what I need to I can write my own game specific controller code using the low level system or download the source and change it to do what I want.

    This is great and couldn't be a much better improvement over the existing (and IMO) horribly broken editor dependent data driven system. Nice work RuneVision.
     
    Last edited: May 17, 2017
    TimHeijden and greg-h like this.
  16. Alverik

    Alverik

    Joined:
    Apr 15, 2016
    Posts:
    417
    I've should've made it clear, I don't agree with the "title" of the thread, I have nothing against your posts. And, yeah, I was generalizing. Thinking out loud. I wasn't aiming my comment at you or anything (else I would've have "replied"). Same when I said "these" I was thinking about a type of people I've seen a lot lately.

    Still, I don't regret generalizing. I've been seeing a whole lot of programmers lately asking for features useful only if you are a good or veteran programmer yourself, things that would complicate things for those who aren't programmers, I've also seen them complain about systems for the same reasons, and not think about everyone else who uses these features. There's people out there who just can't do it the same way an experienced programmer can, and not everyone can get a whole team to build a project. Lots of people work alone or in tiny groups, many times mainly of artist, designers and level designers. Since I've been programming in Unity for a while, I've noticed, the better the UX you want a system to have, and the more the system can do, the more work it is, and it tends to complicate things a lot, you should know. Making code that works is easy, making code easy to use by the end user is hard, specially if you are like Unity, who is trying to cover as much use cases as possible.
     
    Last edited: May 18, 2017
    darbotron likes this.
  17. darbotron

    darbotron

    Joined:
    Aug 9, 2010
    Posts:
    352
    No worries dude, I was in a grump when I got the email notification of your reply to the thread - sorry for taking it personally...

    You are right that the kind of people who belittle others based on their own superiority (for self-defined definitions of superior) suck, and I hope that I didn't do that - it certainly wasn't my intent. Unity is an amazing suite of technologies which enables all of us to make games more easily and I'm glad that it's giving other people what they want from it too.
     
  18. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    Kudos to all for getting the discussion back to respectful and understanding on your own! :)

    And Alex, glad to hear you are happy based on the description of the latest iterations of the system. We're looking forward to be able to show it to you all and get your continued feedback.
     
    darbotron likes this.
  19. perprerp

    perprerp

    Joined:
    Oct 29, 2013
    Posts:
    3
    Hi people, just want to thank you all for the venting and discussion and the ultimate patience towards arriving at understanding. This thread alone is very educational as an introduction to the new input system.
     
    Squidscape likes this.
  20. cdytoby

    cdytoby

    Joined:
    Nov 19, 2014
    Posts:
    181
    OK, found this post and I want to ask one thing:

    Does this new input system also considered VR input? like headtracking, controller position and rotation tracking, and raycast for ui interaction, as well as controller?

    If no, well, I really don't want to write the input system from scratch but I really need it like, in 2 weeks. I totally agree with Alverik but I have no choice, and I already have the input structure in my mind.

    Compare to finding a plugin and test and not work and finding another and again and again, I'd rather develop on my own because I would have better understanding it, and easier to debug.

    One more thing, there is no end for input system because there are endless future like eye tracking, body tracking, or something else that we've never heard of or even thought of. So basically, we need BOTH a "KISS" version so that we can implement something on our own, AND a complex version so that it fits in most cases.
     
    Last edited: Dec 11, 2017
    Alverik likes this.
  21. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    See, this is the problem with input, it becomes unusable the moment everyone wants it to be used for different things. Strictly speaking Input is several different things. I don't want a million options before I can get to PS4 controllers, and you don't want a million options before you get to VR input.

    So they should have separation.
     
    Ryiah and Alverik like this.