This project I’m working on, this cyberpunk corporate financial warfare thing, is pretty simple on the surface. I don’t mean in terms of gameplay; I’m not sure it’ll even qualify as a “game”, per se. Rather, I mean in how it looks when you experience it.
One big disconnect between the consumer and the producer is that the consumer has no idea what actually goes into producing a product. The best that the consumer can do is make logical assumptions, filling in the gaps with knowledge explained or researched, and just glossing over what remains or what’s deemed “unimportant”. One element that I think doesn’t get anywhere near enough interest is user interface design and execution. It’s so critical to the overall operation of the game, but the most attention is receives is when people bitch about how ugly it is or how much room it takes up.
This cyberpunk project is mostly UI. I mean, there’s no little CEO running from map to map collecting resources and turning them into products or anything. You click buttons and slide sliders and maybe enter numbers, and then review your financial empire while you wait for your research or production or distribution or marketing to complete. In order to be as efficient as possible, you’ll need to jump from UI element to UI element, from a broad overview to a micromanagement perspective and back again to make sure you’re not spending money on idle facilities. All of this means I’ve had to really come to grips with one element that I’ve never been really good at: user interfaces. I’m mostly a back-end developer, although most of my jobs have required me to wear the hat of a designer as well. Being a hobbyist developer means that I don’t get to hire anyone to do things like UI for me. I have to do it all myself, which is both a blessing — I get to learn stuff and hopefully get better over time — and a curse — mostly in the form of actual cursing because my UI looks like shit, or doesn’t behave as expected.
Take, for example, the act of opening a simple window. In order to accomplish this you need — a window. This window is normally invisible, or off-screen somewhere so that the user doesn’t see it until it’s needed. Aside from considering whether or not to animate this window (Fade in? Fly in? Zoom in?), the second hurdle beyond design is how to get the window to show up in the first place. In this project, the player will be asked to pick an item to research based on market research that randomly selects a base item type that the population says they’ll buy if certain attributes about that item meet their (intentionally vague) demands. Once the player has decided on which demographic to appease by building their dream product, she’ll need to pick an unused research facility from the map by clicking on it. Currently, these facilities are just small, colored tokens. When the player clicks on one of these, they’ll get a UI panel popup that shows them how much it’s going to cost them to rent the facility each month.
What the user sees is “click the icon, get the window”. What I see is “holy crap where do I attach this UI? How do I get the clicking on the icon to work? How does the act of clicking on the icon tell the window to show itself? And how do I get rid of the window when they decide they don’t want this facility, or when they do choose to rent it?” The biggest hurdles have been where to put the UI, and how to get the action to trigger the UI. In Unity, the UI is now represented by actual game objects, as opposed to the “in pure code” from Unity versions gone by. This means that we can design the UI in the Scene (working) view and see it during edit-time, but it also means that all UI elements are objects in the Scene, like models and lights and audio sources. There’s a certain hierarchy that needs to exist in order for the UI to render, so there’s also a tiered structure that needs to be considered when dealing with different UI elements.
I put the rental fee UI on the facility icon itself, which makes talking between the two easier. What I found very quickly was that with more UI elements comes more complexity when trying to figure out where to put the UI and how to talk to it. Putting the rental fee UI on the icon might work now, but what if there’s a situation where I need to open that UI from somewhere not associated with the icon? I envision a master control panel that will list all research facilities currently rented and operated by the player, so she could click on an item in that list which moves the camera to that point on the map and opens the panel that explains what’s going on with that facility. None of that would be sourced from the item itself; it would need to be called from outside the item, like from a main menu or toolbar. I could add component references between the buttons — wherever they are — and their UI targets, but that results in a lot of spaghetti connections that are difficult to trace when debugging.
The answer was “abstraction” and “oversimplification”. I created a “window manager” which is nothing more than a list of windows in the system. When a window starts up, it registers itself in the master window manager list, and then either stays put, or is hidden (or moved to a point off-screen). With the window manager system attached to the Game Data Object — the global, non-destroyed, singleton object that is accessible from everywhere in the game — I can call methods like ActivateGameWindow() and pass in a name as an argument, like “ResearchRentalUI”. If that UI has self-registered and is in the management stack, then the method will find it and turn it on, activate the animation, or do whatever it needs to do in order to activate that element. This messenger systems ensures that I don’t need to have one specific element know about the existence of another specific element, so long as I don’t misspell the name of the UI element I want to send the message to.
I’m not writing this because this is some kind of revolutionary design technique, but rather because what we see on the surface isn’t always what we think we’re looking at. Sometimes things are more complex, and sometimes they’re more simplistic, and sometimes they’re way out in left field.