Alien Cow Farm is a game for 1-4 players, which has already presented some challenges when it comes to gameplay. But it also meant considerations had to be made for some of the menus. First of all, the number of players will dictate the different play modes that are available, so the order and organization of menus is crucial. Second, there's the usual question of screen space: I needed to be able to display up to four UFOs side-by-side, while still leaving space for the continue button, the controller legend, and the usual screen frame. Sort of like this:
But that's just the 1920x1080 resolution, and remember how much trouble adjusting that causes? My other menus will be mostly safe, because they just have a single panel of buttons anchored in the center of the screen, a setup simple enough for Unity's scaling system to handle automatically. But here, I needed to basically keep everything exactly the way it was, at least horizontally speaking. Simple: it took me a minute to realize, but the thing about the Match Width or Height setting is that it does exactly what it says. By designing for 1920x1080 and setting to Match Width, any other resolution will keep the screen looking exactly the same left-to-right as it does now, and only add extra space on the top and bottom. Again, this is much more complicated than I've made it sound, but the result is exactly what I want. Here's how the 4P Select looks at the 5:4 ratio:
Yes, the colors changed, that's just something I added to randomly pick a different starting color for each UFO every time the menu opens. I've also got code to make sure that no two players can select the same color (even advancing them off the selection whenever another player "locks in" their choice) and to randomly assign NPC colors after all players have made their choices. Trust me, I thought about this a lot.
There was just one problem with the setup described above. The UFO images are in fact not images at all, but actual objects in the scene. Part of the functionality of this menu is that players can rotate around their UFO to see how the different color combinations look from every angle. I wanted to display them here using the render texture trick I picked up, but for some reason, no combination of settings would make it look good. I believe this had to do with how each camera was set to render its target UFO only, and clearing only the depth flags to make that happen didn't play well with the render textures, leaving after-images that never disappeared. So instead those are real cameras, set up using my same PerspectiveCameraOffset script to position them correctly on the screen. The last trick needed to make this solution work was to slightly tweak the cameras' fields of view as the screen's aspect ratio changed. Finding the right relationship between these numbers let me derive a formula which kept each UFO in the center of its panel, no matter the combination of settings. The discrepancy came from mixing the screen-space cameras with the UI rendering of everything else...I tried to avoid it via the render textures method, but the good thing about Unity is that there's always more than one way to solve a problem.
Something else I needed to consider was how to read input. Unity includes built-in support to only let a single player control menu interactions, which is typically what you want, especially for a couch co-op game like this. But on the player select screen, each player should be able to make their choice independently and simultaneously. The answer was to not treat this particular screen as a menu, at least not at first. Without touching the Standalone Input Module (what the built-in is called), I put code in this MenuController's FixedUpdate() function to look for input from any player, and apply it to the corresponding UFO (I've since split this out into four MenuPlayerControllers but the concept is the same). I'm checking for the input I care about every frame, completely independent of whatever Unity's doing for menu navigation. Only when all the players have made their selections does the continue button activate, and then the SIM is back in control and only P1 can click it to continue.
As for knowing how many controllers are plugged in, and when to change the connection messages based on that, the Rewired plugin handles all that for me, thank god. That was the best Unity store purchase I've ever made, and it's both simplified all kinds of tasks and allowed functionality which would've been otherwise impossible. Rewired is a tool which I can rely on to do its job perfectly, allowing me to concentrate on the functionality of the actual game.
Next time: adding animation!