I’ve been extra busy the past two weeks prepping a build for testing, so I unfortunately forgot last week to write a post about what I’ve been doing.
It’s been around 8 months since the last test build that I did, and just testing out the new interface would’ve perhaps been enough, but instead I decided to make some changes, both to the existing areas as well as putting in a first draft of an area for the dot mechanic.
I made a list of tasks that I wanted to accomplish for this specific test build, and set about doing those a bit more diligently. I’d say this is generally a good idea if you want to ship anything: to set out the bullet-points that you need to hit and focus your efforts there. Unfortunately, I still took longer than I expected and didn’t get all of the things on the list done, primarily because I kept subdividing and expanding the tasks.
One of those tasks was to provide a basic tutorial at the start of the game, essentially just a readout with the controls floating in the area near where the player first starts. The issue there is that in order to show the proper controls I need to know if the player is using the mouse/keyboard controls or a gamepad, and it was surprisingly difficult to get this type of information with the input system that I was using.
That system was what I think was a pretty standard system built with the default Unity input system. I had inputs with labels like “Run Button” and “Toggle” and those were mapped to different actions in the game, and different buttons and keys. Unity doesn’t really support automatically remapping these inputs to a bunch of different controller types however, so I had to make a system on top of that where I would have a “XB” and “PS4” version of each input label and then just use some string concatenation to build the proper input strings at runtime based on the name of the input device (which unity thankfully does let me access). But by the time the inputs got to my code, I couldn’t tell whether or not they were coming from a controller or not, as both the XB and PS4 versions of inputs were doubly mapped to keyboard controls as well.
So, I decided to rip out and replace the entire input system in order to get that functionality, as well as to simplify the whole thing for any future input complexities.
In Unity, there’s really only so much you can do without just writing an external dll and handling the input at the OS level (which I may still consider doing). It seemed like the simplest and most straightforward thing to do was to get all of the raw input data that I can out of Unity’s system and then handle the rest entirely in C# code.
The way this worked out in practice was pretty straightforward for the buttons, as unity will just let me poll the event system and has keycodes for all joystick button numbers. With the axes however, I needed to set up input types in the Unity editor just to be able to collect them. I named the inputs “joystick 1 axis 0” through “joystick 1 axis 9”, and set them each to get the axis that matched their name. Although it’s a bit janky, with some string concatenation I now can get all the input info pretty easily into the scripting layer of Unity.
So, once I have all this input data, I need to know what to do with it. In a similar way to the previous input system, I get the name of the controller from Unity and compare it against known strings for each controller type (Xbox 360 or PS4, at the moment, as that’s what I have to test). If I find a controller matching that type, then I set the button mapping for a virtual controller (sort of a platonic ideal of an xbox 360 gamepad) to be equivalent to some pre-mapped structures which simply store the relationship between say, the A button, and a numbered button for that actual controller according to the Unity input system.
I also store another virtual controller for the PC inputs, but here there’s not really an input map. I simply hard map certain keyboard keys to the equivalent buttons. The mouse is stored separately, as it doesn’t exactly correspond to a controller input.
Additionally, whenever I poll each input (whether it be a keyboard press or a button), I update a variable which says where the last input came from,. This is then used to update the final virtual controller state that the game sees. I can also use it later to tell which virtual controller the latest input came from.
Perhaps it’s a bit difficult to explain, but I’ll try to diagram it below:
Overall, I am pretty happy with the results, and it solved the problem of knowing whether or not the player is currently using a controller or the PC controls. However, I still have some old virtual controller management code sitting on top of all of this that I would like to eliminate before I call this system completely rebuilt.
I plan on writing another post this week on some of my thoughts about the testing feedback, but for now I think I will leave it at that. 🙂
Oh, and here’s what the current controls readout looks like in game: