Button glyphs for rebindable inputs
Added 2020-05-29 22:30:31 +0000 UTCI'm going to try and walk you through how I generate the button glyphs for my inputs. That is, the "<press A to> Ollie!" kind of prompts, that show the right button whether you've rebound the input, or are using a keyboard instead of a gamepad, or etc. They're adaptive.
Click here for a video of how it looks in action. The buttons are changing on their own as I touch my keyboard or my gamepad. Get it? Ok, cool!
First of all, it uses ReWired, and no I'm not going to explain how to do it with anything else, but any system should be able to do this.
Gamepads
It is, at its core, a simple system. What I do is map the generic names that ReWired exposes for inputs, stuff like "Action Bottom Row 1" (that's what it calls the X button on an Xbox controller), or "Center 2" (that's the start button), to the appropriate graphic for whatever gamepad you're holding.
The first hurdle is convincing ReWired to even give you that string. What it wants to give you is a string representation localized to your specific controller. So when you ask it the name of the A button, it returns a string that says "A", because it wants to apply a sane label you could theoretically print out. Except if you're instead holding a PS4 controller, it'll call that button "X", which is useless for what we need. It's being too helpful.
This is not simple at all. It is so not simple that I have to paste two giant images to even encompass the process:


What we are doing, in short, is working backwards. We start at the CONTROLLER, rather than the binding. We ask what actions are bound on the controller. Then we iterate through those controller-side bindings, and since we're talking to the controller directly, now we can ask look at the controller's template. That template is what holds the generic-names we're looking for, instead of the unhelpful changes-per-controller names. Then, at long last, we can use that templateElement's descriptiveName to get that " Action Bottom Row 1" style string we crave.
After that? It's actually really easy. That UIManager.GetInputSpriteByName is just a reference into a dictionary. Literally all I do is shove the button glyph graphics into a folder on my disk, and actually name them with the generic names that you find in that descriptiveName. Looks a bit like this in Unity:

So you get to that point and it's like, duh, easy, right? If you want to show PS4 bindings instead of Xbox, you just build your dictionary with the PS4 folder of button glyphs (that also have those filenames) instead of the XBox folder. The trick is just the getting to that name. It's silly. But hey, now you know how!
You can even have an in-game drop-down that lets the player choose which folder they use, and poof, they can have Xbox AND Sony glyphs, whichever matches whatever they're holding. If you really want to get fancy, you add some logic up there in that bit where I'm querying into the controller they're holding, and you can extract a string that says what the controller actually IS. Then you can hardcore which of those goes to which glyph set, and make a generic fallback for when the controller name doesn't match a known. Just make sure you expose the drop-down anyways, because controllers are notoriously finicky in Windows for exactly what they report themselves as.
Keyboard and Mouse
In a way, it's simpler for KBM, but it's also not. Let's go with fancier.
Now you could hardcode a glyph for every single key, but that wouldn't be very efficient, right? Tons of work, and they're all basically the same thing with different letters on top. No no, we're going to use a tiny set of keyboard glyphs that look like this:

... and then we'll just drop a label on top! Bam! Easy!
Here's how these look in-editor, so you've got an idea of what we're building. This is an older GIF without separators, but if you want separators (the slashes or axis-indicators that go between the glyphs), those would be added at this phase too, and just enabled/disabled as you needed them. I recommend building ONE prefab for one of these multi-binding glyphs, and reusing it everywhere, because it's all the same thing. A really dense thing, though, so god help you if you have to propagate changes across a game's UI.

It is easy, sort of, but making the glyphs line up right and scale down and etc gets a little annoying. Here, this will get you started:




It's hard to explain with specifics, since your implementation will vary drastically. That's the gist, though. You want the label on top of the key glyph, and you want it sizing based on the key glyph underneath, so that the wide keys can have more text width-wise on them.
That's the vague gist. Hope it helps! Focus less on copying exactly what I'm doing, and more on drawing out the handful of tips for how to pick the right glyph image, how to easily sort them for picking, how to share keyboard key glyphs across all your keys. Everything else is just hundreds of lines of messy code and special-casing that isn't very clever or fancy, and you can do it however you like.
Now, If you're a code tier, pop on over to the code sample post, and just download my entire class for this.