With the addition of my new UI sprites, I tried to update the Rewired plugin’s UI that they provide. And I realized two things — it has way too many elements and I want to do certain things differently. In fact, I suspect I want to do things differently for any future games too. So I might as well “invest” some time into a new UI. Plus, I will use all my reusable UI prefabs, making it much easier. But there are also fundamental control binding things that I want to change.
Previously, I just glanced over rebinding of keys and buttons and axis with a “Rewired does it”. But now I actually have to use their lower-level API to do all those things myself.
One of the cool feature of Rewired is that it can have a single binding/action have positive and negative components. Such as, “Movement horizontal” instead of two separate “Movement right” and “left”. Unfortunately, this makes binding things to each “end” of the action very… convoluted. Keyboard buttons actually need to be bound to the left/right components. But the controller axis binds to the whole action. This makes displaying UI a mess. I don’t want to show all three options – horizontal (for controller) and left/right (for keyboard). And then what if keyboard decided to bind to horizontal?
In short, I am devolving the actions from full axis to two actions:
And I will manually poll the buttons individually and combine the values into one. In other words, I can bind any button and any axis direction for any movement direction. I don’t care if it’s positive or negative — I will correctly “math it up” into a single value myself. This is almost hackery, but it means I can have the control screen pretty and very clear in its expectations. Four directions, four buttons or four axis — you decide.
Anyway, there is a bunch of UI that comes with a control binding screen, so that’s what I need to add. Firstly, to put the UI in a nice table (like every other game, making it familiar) with headers:
In this case, I have all three connected — keyboard, mouse and controller.
Firstly, I need to show all the binding from each of the input devices:
Then I need to add navigation to the list:
And activation to set the binding (by either pressing submit or “double” clicking):
All I have for setting the binding is just an inline prompt telling to press the button:
There are several things that my input logic needs to deal with, such as my generic inputs that interfere with polling raw inputs at this point. For example, having tiny delays between stopping/starting polling to prevent UI cross-firing inputs. The short story is that many hours were spent getting this working. Not to mention, finding the right way to do all the things I want with Rewired.
This is a crucial part of UI being easy to use — no popups, confirmations, modifier buttons, delays, timeouts, etc. All the “premium” rewired stuff that I just don’t care about. I am providing full control rebinding for each input device with individual axis which is more than many games can claim.
There are a couple extra logic steps I need to take for assigning controls. These would have been done by Rewired’s UI and better use of their features. So here’s non-bindable UI controls that I don’t want the user to rebind and mess up. Basically, if they unbind these they will get stuck and will not be able to navigate the UI.
Honestly, I am not even sure if I need to show them. They are just nice to check to know what to use. Although, if you got to the controls menu, you already do… I will likely not show them. But then I need some feedback when they conflict, to notify the user that they unbound something. And I might add that later, but I really am spending way too long on this already at the moment.
I also have several controls that actually can “conflict” with other controls, but are fine to overlap, for example UI and gameplay actions:
There are basically three control “groups” I use: “gameplay”, “system global” and “system menu”. System global action are stuff like the Escape button, which can never be rebound and is always available — in menus or gameplay. A less strict version is the system menu actions like the arrow navigation, which also cannot be rebound but is only available in menus — it doesn’t need to be in gameplay and thus can be rebound to the same keys for gameplay. Finally, gameplay is every which button or axis the user wants to assign, as long as they don’t conflict with the system global ones or each other. Anyway, getting all this logic properly working and tested is a task in itself.
I also need a de-bind button and show a hint for this to the user:
This unbinds all (connected) input devices, which may not be desired. But honestly, how often do you need to do this? The alternative is that I need the user to be able to navigate between input devices.
Anyway, that about does it for my controls binding UI. Important, yet one-time user experience. It took way too long to make, added additional maintenance, messed with UI, and isn’t as good as I wanted. Sounds about on par with everything else… Well, hopefully, I can port it to future games without too much effort. Hopefully, this hypothetical future game actually becomes a reality.